Bobarik31p 1 month ago
parent
commit
108af9a3a6

+ 26 - 0
.idea/appInsightsSettings.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AppInsightsSettings">
+    <option name="tabSettings">
+      <map>
+        <entry key="Firebase Crashlytics">
+          <value>
+            <InsightsFilterSettings>
+              <option name="connection">
+                <ConnectionSetting>
+                  <option name="appId" value="PLACEHOLDER" />
+                  <option name="mobileSdkAppId" value="" />
+                  <option name="projectId" value="" />
+                  <option name="projectNumber" value="" />
+                </ConnectionSetting>
+              </option>
+              <option name="signal" value="SIGNAL_UNSPECIFIED" />
+              <option name="timeIntervalDays" value="THIRTY_DAYS" />
+              <option name="visibilityType" value="ALL" />
+            </InsightsFilterSettings>
+          </value>
+        </entry>
+      </map>
+    </option>
+  </component>
+</project>

+ 28 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -1,6 +1,34 @@
 <component name="InspectionProjectProfileManager">
   <profile version="1.0">
     <option name="myName" value="Project Default" />
+    <inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+      <option name="previewFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+      <option name="previewFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+      <option name="previewFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+      <option name="previewFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
     <inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
       <option name="composableFile" value="true" />
       <option name="previewFile" value="true" />

+ 0 - 1
.idea/misc.xml

@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ExternalStorageConfigurationManager" enabled="true" />
   <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

+ 0 - 318
.idea/other.xml

@@ -1,318 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="direct_access_persist.xml">
-    <option name="deviceSelectionList">
-      <list>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="27" />
-          <option name="brand" value="DOCOMO" />
-          <option name="codename" value="F01L" />
-          <option name="id" value="F01L" />
-          <option name="manufacturer" value="FUJITSU" />
-          <option name="name" value="F-01L" />
-          <option name="screenDensity" value="360" />
-          <option name="screenX" value="720" />
-          <option name="screenY" value="1280" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="28" />
-          <option name="brand" value="DOCOMO" />
-          <option name="codename" value="SH-01L" />
-          <option name="id" value="SH-01L" />
-          <option name="manufacturer" value="SHARP" />
-          <option name="name" value="AQUOS sense2 SH-01L" />
-          <option name="screenDensity" value="480" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2160" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="31" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="a51" />
-          <option name="id" value="a51" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy A51" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="akita" />
-          <option name="id" value="akita" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 8a" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="b0q" />
-          <option name="id" value="b0q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy S22 Ultra" />
-          <option name="screenDensity" value="600" />
-          <option name="screenX" value="1440" />
-          <option name="screenY" value="3088" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="32" />
-          <option name="brand" value="google" />
-          <option name="codename" value="bluejay" />
-          <option name="id" value="bluejay" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 6a" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="caiman" />
-          <option name="id" value="caiman" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 9 Pro" />
-          <option name="screenDensity" value="360" />
-          <option name="screenX" value="960" />
-          <option name="screenY" value="2142" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="comet" />
-          <option name="id" value="comet" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 9 Pro Fold" />
-          <option name="screenDensity" value="390" />
-          <option name="screenX" value="2076" />
-          <option name="screenY" value="2152" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="29" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="crownqlteue" />
-          <option name="id" value="crownqlteue" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy Note9" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="2220" />
-          <option name="screenY" value="1080" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="dm3q" />
-          <option name="id" value="dm3q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy S23 Ultra" />
-          <option name="screenDensity" value="600" />
-          <option name="screenX" value="1440" />
-          <option name="screenY" value="3088" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="e1q" />
-          <option name="id" value="e1q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy S24" />
-          <option name="screenDensity" value="480" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2340" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="google" />
-          <option name="codename" value="felix" />
-          <option name="id" value="felix" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel Fold" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="2208" />
-          <option name="screenY" value="1840" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="felix" />
-          <option name="id" value="felix" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel Fold" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="2208" />
-          <option name="screenY" value="1840" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="google" />
-          <option name="codename" value="felix_camera" />
-          <option name="id" value="felix_camera" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel Fold (Camera-enabled)" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="2208" />
-          <option name="screenY" value="1840" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="gts8uwifi" />
-          <option name="id" value="gts8uwifi" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy Tab S8 Ultra" />
-          <option name="screenDensity" value="320" />
-          <option name="screenX" value="1848" />
-          <option name="screenY" value="2960" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="husky" />
-          <option name="id" value="husky" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 8 Pro" />
-          <option name="screenDensity" value="390" />
-          <option name="screenX" value="1008" />
-          <option name="screenY" value="2244" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="30" />
-          <option name="brand" value="motorola" />
-          <option name="codename" value="java" />
-          <option name="id" value="java" />
-          <option name="manufacturer" value="Motorola" />
-          <option name="name" value="G20" />
-          <option name="screenDensity" value="280" />
-          <option name="screenX" value="720" />
-          <option name="screenY" value="1600" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="komodo" />
-          <option name="id" value="komodo" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 9 Pro XL" />
-          <option name="screenDensity" value="360" />
-          <option name="screenX" value="1008" />
-          <option name="screenY" value="2244" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="google" />
-          <option name="codename" value="lynx" />
-          <option name="id" value="lynx" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 7a" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="31" />
-          <option name="brand" value="google" />
-          <option name="codename" value="oriole" />
-          <option name="id" value="oriole" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 6" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="google" />
-          <option name="codename" value="panther" />
-          <option name="id" value="panther" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 7" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="q5q" />
-          <option name="id" value="q5q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy Z Fold5" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1812" />
-          <option name="screenY" value="2176" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="30" />
-          <option name="brand" value="google" />
-          <option name="codename" value="r11" />
-          <option name="id" value="r11" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel Watch" />
-          <option name="screenDensity" value="320" />
-          <option name="screenX" value="384" />
-          <option name="screenY" value="384" />
-          <option name="type" value="WEAR_OS" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="30" />
-          <option name="brand" value="google" />
-          <option name="codename" value="redfin" />
-          <option name="id" value="redfin" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 5" />
-          <option name="screenDensity" value="440" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2340" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="shiba" />
-          <option name="id" value="shiba" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 8" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2400" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="33" />
-          <option name="brand" value="google" />
-          <option name="codename" value="tangorpro" />
-          <option name="id" value="tangorpro" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel Tablet" />
-          <option name="screenDensity" value="320" />
-          <option name="screenX" value="1600" />
-          <option name="screenY" value="2560" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="34" />
-          <option name="brand" value="google" />
-          <option name="codename" value="tokay" />
-          <option name="id" value="tokay" />
-          <option name="manufacturer" value="Google" />
-          <option name="name" value="Pixel 9" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1080" />
-          <option name="screenY" value="2424" />
-        </PersistentDeviceSelectionData>
-        <PersistentDeviceSelectionData>
-          <option name="api" value="29" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="x1q" />
-          <option name="id" value="x1q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy S20" />
-          <option name="screenDensity" value="480" />
-          <option name="screenX" value="1440" />
-          <option name="screenY" value="3200" />
-        </PersistentDeviceSelectionData>
-      </list>
-    </option>
-  </component>
-</project>

+ 6 - 0
.idea/vcs.xml

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

+ 11 - 0
app/build.gradle.kts

@@ -70,6 +70,17 @@ dependencies {
     implementation(libs.gotrue.kt)
     implementation(libs.realtime.kt)
     implementation (libs.androidx.material3)
+    implementation(libs.ktor.client.okhttp)
+    implementation(libs.androidx.navigation.compose)
+    implementation(libs.androidx.navigation.fragment)
+    implementation(libs.androidx.navigation.ui)
+    implementation(libs.androidx.navigation.dynamic.features.fragment)
+    implementation(libs.supabase.gotrue.kt)
+
+
+
+
+
 
 
 

+ 6 - 1
app/src/main/java/com/example/tasks/MainActivity.kt

@@ -11,9 +11,11 @@ import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import com.example.tasks.navigation.Navigation
 import com.example.tasks.screens.SignIn
 import com.example.tasks.screens.Start
 import com.example.tasks.ui.theme.TasksTheme
+import com.example.tasks.viewModels.AuthViewModel
 
 class MainActivity : ComponentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -21,7 +23,10 @@ class MainActivity : ComponentActivity() {
         enableEdgeToEdge()
         setContent {
             TasksTheme {
-                SignIn()
+                val viewModel = AuthViewModel()
+                Navigation(viewModel)
+
+
             }
         }
     }

+ 27 - 0
app/src/main/java/com/example/tasks/components/SharedPreferenceHelper.kt

@@ -0,0 +1,27 @@
+package com.example.tasks.components
+
+import android.content.Context
+
+
+class SharedPreferenceHelper(private val context: Context) {
+
+    companion object{
+        private const val MY_PREF_KEY = "MY_PREF"
+    }
+
+    fun saveStringData(key:String,data:String?)
+    {
+        val sharedPreferences = context.getSharedPreferences(MY_PREF_KEY,Context.MODE_PRIVATE)
+        sharedPreferences.edit().putString(key,data).apply()
+    }
+    fun getStringData(key:String):String?
+    {
+        val sharedPreferences = context.getSharedPreferences(MY_PREF_KEY,Context.MODE_PRIVATE)
+        return sharedPreferences.getString(key,null)
+    }
+    fun clearPreferences()
+    {
+        val sharedPreferences = context.getSharedPreferences(MY_PREF_KEY,Context.MODE_PRIVATE)
+        sharedPreferences.edit().clear().apply()
+    }
+}

+ 8 - 0
app/src/main/java/com/example/tasks/model/UserState.kt

@@ -0,0 +1,8 @@
+package com.example.tasks.model
+
+
+sealed class UserState {
+    object Loading: UserState()
+    data class Success(val message:String):UserState()
+    data class Error(val message:String):UserState()
+}

+ 46 - 0
app/src/main/java/com/example/tasks/navigation/Navigation.kt

@@ -0,0 +1,46 @@
+package com.example.tasks.navigation
+
+import androidx.compose.runtime.Composable
+import androidx.navigation.NavType
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import androidx.navigation.navArgument
+import com.example.tasks.screens.CreateProfile
+import com.example.tasks.screens.EnterOTP
+import com.example.tasks.screens.SignIn
+import com.example.tasks.screens.Start
+import com.example.tasks.viewModels.AuthViewModel
+
+@Composable
+fun Navigation(viewModel: AuthViewModel) {
+    val navController = rememberNavController()
+    NavHost(navController = navController, startDestination = Screen.Start.route)
+    {
+        composable(Screen.Start.route)
+        {
+            Start(navController)
+        }
+        composable(Screen.SignIn.route)
+        {
+            SignIn(navController,viewModel)
+
+        }
+            composable(Screen.EnterOTP.route + "/{email}", arguments = listOf(
+            navArgument("email") {
+                type = NavType.StringType
+            }
+        ))
+        {
+            val email = it.arguments!!.getString("email")
+            EnterOTP(navController = navController, email = email!!,viewModel)
+
+
+        }
+        composable(Screen.CreateProfile.route)
+        {
+            CreateProfile()
+
+        }
+    }
+}

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

@@ -0,0 +1,18 @@
+package com.example.tasks.navigation
+
+
+sealed class Screen(val route:String) {
+    object Start: Screen("start")
+    object SignIn:Screen("sinIn")
+    object EnterOTP: Screen("enterOTP")
+    object  CreateProfile: Screen("createProfile")
+
+    fun withArg(vararg args: String): String {
+        return buildString {
+            append(route)
+            args.forEach { arg ->
+                append("/$arg")
+            }
+        }
+    }
+}

+ 7 - 0
app/src/main/java/com/example/tasks/screens/CreateProfile.kt

@@ -0,0 +1,7 @@
+package com.example.tasks.screens
+
+import androidx.compose.runtime.Composable
+
+@Composable
+fun CreateProfile() {
+}

+ 412 - 0
app/src/main/java/com/example/tasks/screens/EnterOTP.kt

@@ -0,0 +1,412 @@
+package com.example.tasks.screens
+
+import android.health.connect.datatypes.units.Length
+import android.widget.Toast
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+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.layout.wrapContentSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardActions
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+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.draw.clip
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+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.delay
+
+@Composable
+fun EnterOTP(navController: NavController,email:String,viewModel: AuthViewModel) {
+    val userState by viewModel.userState
+    var currentUserState by remember { mutableStateOf("") }
+    val focusManager = LocalFocusManager.current
+    var flag = remember { mutableStateOf(false) }
+    val context = LocalContext.current
+    val keyboardController = LocalSoftwareKeyboardController.current
+    val textList = listOf(
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        },
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        },
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        },
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        },
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        },
+        remember {
+            mutableStateOf(
+                TextFieldValue(
+                    text = "",
+                    selection = TextRange(0)
+                )
+            )
+        }
+
+    )
+
+    val requesterList = listOf(
+        remember { FocusRequester() },
+        remember { FocusRequester() },
+        remember { FocusRequester() },
+        remember { FocusRequester() },
+        remember { FocusRequester() },
+        remember { FocusRequester() }
+
+    )
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .background(MaterialTheme.colorScheme.background)
+            .pointerInput(Unit) {
+                detectTapGestures(onTap = {
+                    keyboardController?.hide()
+                    focusManager.clearFocus()
+                })
+            }
+    )
+    {
+        Row(modifier = Modifier
+            .fillMaxWidth()
+            .padding(top = 40.dp, start = 20.dp),
+            horizontalArrangement = Arrangement.Start,
+            verticalAlignment = Alignment.Top) {
+            Button(onClick = {navController.navigate(Screen.SignIn.route)},
+                shape = RoundedCornerShape(size = 8.dp),
+                colors = ButtonDefaults.buttonColors(
+                    containerColor = Color(0xFFF5F5F9)
+                ),
+                modifier = Modifier
+                    .width(32.dp)
+                    .height(32.dp),contentPadding = PaddingValues(1.dp)
+            )
+            {
+                Icon(imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft, contentDescription = "Назад",tint = Color.Black,modifier = Modifier.size(20.dp))
+            }
+        }
+    }
+
+    Column(
+        modifier = Modifier
+            .fillMaxSize(),
+        verticalArrangement = Arrangement.Center,
+        horizontalAlignment = Alignment.CenterHorizontally
+    ) {
+        Text(text = "Введите код из E-mail", fontSize = 17.sp)
+        Row(
+            modifier = Modifier
+                .align(Alignment.CenterHorizontally)
+        ) {
+            ContentView(textList,requesterList)
+        }
+        Spacer(modifier = Modifier.height(30.dp))
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(top = 10.dp),
+            horizontalAlignment = Alignment.CenterHorizontally
+        )
+        {
+
+            var timer by remember { mutableIntStateOf(60) }
+            LaunchedEffect(key1 = timer) {
+                if (timer > 0) {
+                    delay(1_000)
+                    timer -= 1
+                }
+            }
+            if(timer!=0)
+            {
+                Text(
+                    text = "Отправить код повторно можно",
+                    fontSize = 15.sp,
+                    color = Color(0xFF939396)
+                )
+                Text(
+                    text = "будет через $timer секунд",
+                    fontSize = 15.sp,
+                    color = Color(0xFF939396)
+                )
+
+            }
+            else {
+                Text(
+                    text = "Отправить код заново",
+                    fontSize = 15.sp,
+                    color = Color(0xFF939396),
+                    modifier = Modifier.clickable { viewModel.onSignInEmailCode(context,email)}
+                )
+            }
+
+        }
+
+        Button(
+            onClick = {
+                val token = token(textList)
+                viewModel.verifyOTP(email, token)
+                 flag.value = true     },
+            Modifier
+                .fillMaxWidth()
+                .height(50.dp),
+            shape = RoundedCornerShape(20),
+            colors = ButtonColors(
+                contentColor = Color.White,
+                containerColor = Color.Blue,
+                disabledContentColor = Color.White,
+                disabledContainerColor = Color.Gray
+            )
+        ) {
+            Text(text = "Далее", fontSize = 14.sp)
+
+        }
+       if(flag.value){
+           when (userState) {
+               is UserState.Loading -> {
+                   LoadingComponent()
+               }
+
+               is UserState.Success -> {
+                   val message = (userState as UserState.Success).message
+                   currentUserState = message
+                   navController.navigate(Screen.CreateProfile.route)
+                   flag.value = false
+               }
+
+               is UserState.Error -> {
+                   val message = (userState as UserState.Error).message
+                   currentUserState = message
+                   Toast.makeText(context,"Неверный код",Toast.LENGTH_SHORT).show()
+                   flag.value = false
+               }
+           }
+
+           if (currentUserState.isNotEmpty()) {
+               println(currentUserState)
+           }
+       }
+
+    }
+
+}
+@Composable
+fun LoadingComponent() {
+    Column(modifier = Modifier.fillMaxSize(),
+        verticalArrangement = Arrangement.Center,
+        horizontalAlignment = Alignment.CenterHorizontally) {
+        CircularProgressIndicator()
+    }
+}
+private fun token ( textList: List<MutableState<TextFieldValue>>):String{
+    var code = ""
+    for(text in textList)
+    {
+        code += text.value.text
+    }
+    return code
+}
+
+
+
+
+fun nextFocus(
+    textList: List<MutableState<TextFieldValue>>,
+    requesterList: List<FocusRequester>)
+{
+    for(index in textList.indices)
+    {
+        if(textList[index].value.text == "")
+        {
+            if(index<textList.size)
+            {
+                requesterList[index].requestFocus()
+                break
+            }
+        }
+    }
+}
+
+@Composable
+fun inputWiew(
+    value:TextFieldValue,
+    onValueChange: (value:TextFieldValue) -> Unit,
+    focusRequester: FocusRequester
+)
+{
+    BasicTextField(
+        readOnly = false,
+        value = value,
+        onValueChange = onValueChange,
+
+        modifier = Modifier
+            .clip(RoundedCornerShape(10.dp))
+            .padding(horizontal = 7.dp)
+            .clip(RoundedCornerShape(8.dp))
+            .wrapContentSize()
+            .background(Color(0xFFF5F5F9))
+            .focusRequester(focusRequester)
+            .border(1.dp, Color(0xFFEBEBEB)),
+        singleLine = true,
+        maxLines = 1,
+        decorationBox = {
+                innerTextField ->
+            Box(modifier = Modifier
+                .width(40.dp)
+                .height(40.dp),
+                contentAlignment = Alignment.Center,
+            )
+            {
+                innerTextField()
+            }
+
+        },
+        cursorBrush = SolidColor(Color.Black),
+        textStyle = TextStyle(
+            color = Color.Black,
+            fontSize = 20.sp,
+            textAlign = TextAlign.Center
+        ),
+        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
+        keyboardActions = KeyboardActions(
+            onDone = null
+        )
+    )
+}
+
+@Composable
+fun ContentView(
+    textList: List<MutableState<TextFieldValue>>,
+    requesterList: List<FocusRequester>,
+)
+{
+
+
+    Surface {
+        Box(
+            modifier = Modifier
+                .fillMaxWidth()
+        )
+        {
+            Row(
+                modifier = Modifier
+                    .padding(horizontal = 16.dp)
+                    .padding(top = 50.dp)
+                    .align(Alignment.Center)
+            ) {
+                for(i in textList.indices)
+                {
+                    inputWiew(
+                        value = textList[i].value,
+                        onValueChange = {newValue ->
+                            if(textList[i].value.text!="")
+                            {
+                                if(newValue.text=="")
+                                {
+                                    textList[i].value = TextFieldValue(
+                                        text = "",
+                                        selection = TextRange(0)
+                                    )
+                                }
+                                return@inputWiew
+                            }
+                            textList[i].value = TextFieldValue(
+                                text = newValue.text,
+                                selection = TextRange(newValue.text.length)
+                            )
+                            nextFocus(textList,requesterList)},
+                        focusRequester = requesterList[i])
+
+                }
+
+
+
+
+            }
+        }
+    }
+}
+
+
+
+
+

+ 18 - 8
app/src/main/java/com/example/tasks/screens/SignIn.kt

@@ -2,39 +2,48 @@ package com.example.tasks.screens
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 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.platform.LocalContext
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
 import com.example.tasks.components.CustomEmail
 import com.example.tasks.components.CustomPassword
+import com.example.tasks.navigation.Screen
+import com.example.tasks.viewModels.AuthViewModel
 
 @Composable
-fun SignIn() {
+fun SignIn(navController:NavController, viewModel: AuthViewModel) {
+    val context = LocalContext.current
     val email = remember { mutableStateOf("") }
-    val password = remember { mutableStateOf("") }
     Column(
-        modifier = Modifier.fillMaxWidth(),
+        modifier = Modifier.fillMaxSize().padding(10.dp),
         verticalArrangement = Arrangement.Center,
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
         CustomEmail(search = email.value, onValueChange = { email.value = it })
-        CustomPassword(
-            text = "Введите пароль",
-            search = password.value,
-            onValueChange = { password.value = it })
+        Spacer(Modifier.height(30.dp))
         Button(
-            onClick = { /*TODO*/ },
+            onClick = { viewModel.onSignInEmailCode(context,email.value)
+                      navController.navigate(Screen.EnterOTP.withArg(email.value))},
             Modifier
                 .fillMaxWidth()
                 .height(50.dp),
+            shape = RoundedCornerShape(20),
             colors = ButtonColors(
                 contentColor = Color.White,
                 containerColor = Color.Blue,
@@ -42,6 +51,7 @@ fun SignIn() {
                 disabledContainerColor = Color.Gray
             )
         ) {
+            Text(text = "Далее", fontSize = 14.sp)
 
         }
 

+ 7 - 21
app/src/main/java/com/example/tasks/screens/Start.kt

@@ -19,21 +19,23 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import com.example.tasks.navigation.Screen
 
-@Preview
 @Composable
-fun Start() {
+fun Start(navController: NavController) {
     Column(
         modifier = Modifier.fillMaxSize(),
-        verticalArrangement = Arrangement.Center,
+        verticalArrangement = Arrangement.SpaceAround,
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
+        Text(text = "ДикиеЯгоды", fontSize = 30.sp, color = Color.Magenta)
         Button(
-            onClick = { /*TODO*/ },
+            onClick = {navController.navigate(Screen.SignIn.route) },
             modifier = Modifier
                 .fillMaxWidth(0.7f)
                 .height(50.dp),
-            shape = RoundedCornerShape(40),
+            shape = RoundedCornerShape(20),
             colors = ButtonColors(
                 contentColor = Color.White,
                 containerColor = Color.Blue,
@@ -43,22 +45,6 @@ fun Start() {
         ) {
             Text(text = "Вход",fontSize = 14.sp)
         }
-        Spacer(modifier = Modifier.height(10.dp))
-        Button(
-            onClick = { /*TODO*/ },
-            modifier = Modifier
-                .fillMaxWidth(0.7f)
-                .height(50.dp),
-            shape = RoundedCornerShape(40),
-            colors = ButtonColors(
-                contentColor = Color.White,
-                containerColor = Color.Blue,
-                disabledContentColor = Color.White,
-                disabledContainerColor = Color.Blue
-            )
-        ) {
-            Text(text = "Регистрация", fontSize = 14.sp)
-        }
 
     }
 

+ 149 - 0
app/src/main/java/com/example/tasks/viewModels/AuthViewModel.kt

@@ -0,0 +1,149 @@
+package com.example.tasks.viewModels
+
+import android.content.Context
+import android.util.Log
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.tasks.components.Constants
+import com.example.tasks.components.SharedPreferenceHelper
+import com.example.tasks.model.UserState
+import io.github.jan.supabase.gotrue.OtpType
+import io.github.jan.supabase.gotrue.auth
+import io.github.jan.supabase.gotrue.providers.builtin.Email
+import io.github.jan.supabase.gotrue.providers.builtin.OTP
+import kotlinx.coroutines.launch
+
+
+class AuthViewModel : ViewModel() {
+    private val _userState = mutableStateOf<UserState>(UserState.Loading)
+    val userState: State<UserState> = _userState
+    fun onSignInEmailCode(context: Context, emailUser: String) {
+        viewModelScope.launch {
+            try {
+                _userState.value = UserState.Loading
+                Constants.supabase.auth.signInWith(OTP) {
+                    email = emailUser
+                    createUser = false
+                }
+                saveToken(context)
+                _userState.value = UserState.Success("Successful sign in")
+
+            } catch (e: Exception) {
+                _userState.value = UserState.Error("Error: ${e.message}")
+
+            }
+
+        }
+    }
+
+    private fun saveToken(context: Context) {
+        viewModelScope.launch {
+            val accessToken = Constants.supabase.auth.currentAccessTokenOrNull()
+            val sharedPref = SharedPreferenceHelper(context)
+            sharedPref.saveStringData("accessToken", accessToken)
+        }
+    }
+
+    private fun getToken(context: Context): String? {
+        val sharedPref = SharedPreferenceHelper(context)
+        return sharedPref.getStringData("accessToken")
+
+    }
+
+    fun onSignUpEmailCode(emailUser: String) {
+        viewModelScope.launch {
+            try {
+                Constants.supabase.auth.signInWith(OTP) {
+                    email = emailUser
+                    createUser = true
+                }
+
+            } catch (e: Exception) {
+                println(e.message.toString())
+
+            }
+
+        }
+    }
+
+    fun verifyOTP(emailUser: String, token: String) {
+        viewModelScope.launch {
+            try {
+                _userState.value = UserState.Loading
+                Constants.supabase.auth.verifyEmailOtp(
+                    type = OtpType.Email.EMAIL,
+                    email = emailUser,
+                    token = token
+                )
+                _userState.value = UserState.Success("the correct code")
+                Log.d("o", "gooood")
+
+            } catch (e: Exception) {
+                Log.d("o", "baaad")
+                _userState.value = UserState.Error("Error: ${e.message}")
+
+            }
+
+        }
+    }
+
+    fun onSignInEmailPassword(emailUser: String, passwordUser: String) {
+        viewModelScope.launch {
+            try {
+                val user = Constants.supabase.auth.signInWith(Email) {
+                    email = emailUser
+                    password = passwordUser
+                }
+                println(user.toString())
+                println(Constants.supabase.auth.currentUserOrNull()!!.id)
+                println("Success")
+            } catch (e: Exception) {
+                println("Error")
+                println(e.message.toString())
+            }
+        }
+    }
+
+    fun onSignUpEmail(emailUser: String, passwordUser: String) {
+        viewModelScope.launch {
+            try {
+                var user = Constants.supabase.auth.signUpWith(Email) {
+                    email = emailUser
+                    password = passwordUser
+                }
+                println(user.toString())
+                println(Constants.supabase.auth.currentUserOrNull()!!.id)
+                println("Success")
+            } catch (e: Exception) {
+                println("Error")
+                println(e.message.toString())
+            }
+
+        }
+    }
+
+
+    fun isUserLoggedIn(context: Context){
+        viewModelScope.launch {
+            try {
+                val token = getToken(context)
+                if (token.isNullOrEmpty()){
+                    _userState.value = UserState.Error("User is not logged in")
+                }
+                else
+                {
+                    Constants.supabase.auth.retrieveUser(token)
+                    Constants.supabase.auth.refreshCurrentSession()
+                    saveToken(context)
+                    _userState.value = UserState.Success("User is logged in")
+                }
+
+            }
+            catch (e:Exception){
+                _userState.value = UserState.Error("Error: ${e.message}")
+            }
+        }
+    }
+}

+ 14 - 2
gradle/libs.versions.toml

@@ -6,14 +6,22 @@ coreKtx = "1.13.1"
 junit = "4.13.2"
 junitVersion = "1.2.1"
 espressoCore = "3.6.1"
+ktorClientCio = "2.3.4"
+ktorClientOkhttp = "2.3.12"
 lifecycleRuntimeKtx = "2.8.5"
 activityCompose = "1.9.2"
-composeBom = "2024.09.00"
+composeBom = "2024.09.01"
 material3 = "1.3.0"
+navigationCompose = "2.8.0"
+supabaseKt = "2.6.1"
 
 [libraries]
 androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
 androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
+androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
+androidx-navigation-dynamic-features-fragment = { module = "androidx.navigation:navigation-dynamic-features-fragment", version.ref = "navigationCompose" }
+androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment", version.ref = "navigationCompose" }
+androidx-navigation-ui = { module = "androidx.navigation:navigation-ui", version.ref = "navigationCompose" }
 bom = { module = "io.github.jan-tennert.supabase:bom", version.ref = "bom" }
 gotrue-kt = { module = "io.github.jan-tennert.supabase:gotrue-kt" }
 junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -29,9 +37,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" }
 
+ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktorClientCio" }
+ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktorClientOkhttp" }
 postgrest-kt = { module = "io.github.jan-tennert.supabase:postgrest-kt" }
 realtime-kt = { module = "io.github.jan-tennert.supabase:realtime-kt" }
-androidx-material3-android = { group = "androidx.compose.material3", name = "material3-android", version.ref = "material3Android" }
+supabase-gotrue = { module = "io.github.jan-tennert.supabase:supabase-gotrue", version.ref = "bom" }
+supabase-gotrue-kt = { module = "io.github.jan-tennert.supabase:gotrue-kt", version.ref = "bom" }
+supabase-kt = { module = "io.supabase:supabase-kt", version.ref = "supabaseKt" }
 
 [plugins]
 android-application = { id = "com.android.application", version.ref = "agp" }