Jelajahi Sumber

app: add password reset, start developmennt of screen for profile

Bobarik31p 5 hari lalu
induk
melakukan
930b2878af
28 mengubah file dengan 679 tambahan dan 547 penghapusan
  1. 3 0
      App/.idea/deploymentTargetSelector.xml
  2. 0 329
      App/.idea/other.xml
  3. 84 0
      App/.kotlin/errors/errors-1732042634140.log
  4. 5 4
      App/app/build.gradle.kts
  5. 10 0
      App/app/src/main/java/com/example/mystictale/Constants/SupabaseConnect.kt
  6. 0 67
      App/app/src/main/java/com/example/mystictale/MainActivity.kt
  7. 179 0
      App/app/src/main/java/com/example/mystictale/Screen/Profile.kt
  8. 72 10
      App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/NewPassword.kt
  9. 45 27
      App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/PasswordRecovery.kt
  10. 3 4
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationDateOfBirth.kt
  11. 21 1
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationGender.kt
  12. 2 2
      App/app/src/main/java/com/example/mystictale/Screen/signIn/SignIn.kt
  13. 51 31
      App/app/src/main/java/com/example/mystictale/ViewModels/AuthViewModel.kt
  14. 0 12
      App/app/src/main/java/com/example/mystictale/models/AppMetadata.kt
  15. 0 11
      App/app/src/main/java/com/example/mystictale/models/ExampleJson2KtKotlin.kt
  16. 0 13
      App/app/src/main/java/com/example/mystictale/models/UserMetadata.kt
  17. 15 20
      App/app/src/main/java/com/example/mystictale/models/Users.kt
  18. 5 0
      App/app/src/main/java/com/example/mystictale/navigation/Navigation.kt
  19. 1 0
      App/app/src/main/java/com/example/mystictale/navigation/Screens.kt
  20. 50 0
      App/app/src/main/java/com/example/mystictale/resources/GetUserByEmail.kt
  21. 7 5
      App/app/src/main/java/com/example/mystictale/resources/components/GenericTextField.kt
  22. 7 5
      App/app/src/main/java/com/example/mystictale/resources/components/PasswordTextField.kt
  23. 80 0
      App/app/src/main/java/com/example/mystictale/resources/components/ProfileTextField.kt
  24. 7 5
      App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/DateOfBirthTextField.kt
  25. 22 0
      App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/FormattingDateForDatabase.kt
  26. TEMPAT SAMPAH
      App/app/src/main/res/drawable/girl.png
  27. 2 1
      App/build.gradle.kts
  28. 8 0
      App/gradle/libs.versions.toml

+ 3 - 0
App/.idea/deploymentTargetSelector.xml

@@ -13,6 +13,9 @@
         </DropdownSelection>
         <DialogSelection />
       </SelectionState>
+      <SelectionState runConfigName="Profile">
+        <option name="selectionMode" value="DROPDOWN" />
+      </SelectionState>
     </selectionStates>
   </component>
 </project>

+ 0 - 329
App/.idea/other.xml

@@ -1,329 +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="34" />
-          <option name="brand" value="Lenovo" />
-          <option name="codename" value="TB370FU" />
-          <option name="id" value="TB370FU" />
-          <option name="manufacturer" value="Lenovo" />
-          <option name="name" value="Tab P12" />
-          <option name="screenDensity" value="340" />
-          <option name="screenX" value="1840" />
-          <option name="screenY" value="2944" />
-        </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="34" />
-          <option name="brand" value="samsung" />
-          <option name="codename" value="q6q" />
-          <option name="id" value="q6q" />
-          <option name="manufacturer" value="Samsung" />
-          <option name="name" value="Galaxy Z Fold6" />
-          <option name="screenDensity" value="420" />
-          <option name="screenX" value="1856" />
-          <option name="screenY" value="2160" />
-        </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>
-      </list>
-    </option>
-  </component>
-</project>

+ 84 - 0
App/.kotlin/errors/errors-1732042634140.log

@@ -0,0 +1,84 @@
+kotlin version: 2.0.0
+error message: Daemon compilation failed: null
+java.lang.Exception
+	at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
+	at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
+	at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
+	at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
+	at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
+	at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
+	at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
+	at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
+	at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
+	at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
+	at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
+	at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
+	at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
+	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
+	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
+	at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
+	at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
+	at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
+	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+	at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
+	at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
+	at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
+	at org.gradle.internal.Factories$1.create(Factories.java:31)
+	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:264)
+	at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:128)
+	at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:133)
+	at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
+	at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
+	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
+	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
+	at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
+	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
+	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
+	at java.base/java.lang.Thread.run(Thread.java:840)
+Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups5924806711967660426
+	at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:272)
+	at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:105)
+	at java.base/java.nio.file.Files.delete(Files.java:1152)
+	at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
+	at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
+	at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
+	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
+	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
+	at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
+	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
+	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
+	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
+	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
+	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
+	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
+	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
+	at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
+	at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
+	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
+	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
+	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:676)
+	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
+	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1661)
+	at jdk.internal.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
+	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
+	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360)
+	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
+	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
+	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
+	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
+	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
+	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
+	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
+	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
+	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
+	... 3 more
+
+

+ 5 - 4
App/app/build.gradle.kts

@@ -2,6 +2,7 @@ plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.jetbrains.kotlin.android)
     alias(libs.plugins.compose.compiler)
+    kotlin("plugin.serialization") version "1.4.21"
 
 }
 
@@ -82,10 +83,10 @@ dependencies {
     implementation (libs.androidx.fragment.ktx)
     implementation (libs.androidx.lifecycle.viewmodel.ktx)
     implementation (libs.androidx.lifecycle.viewmodel.compose)
-    implementation("com.squareup.okhttp3:okhttp:4.10.0")
-    implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
-    implementation ("com.google.code.gson:gson:2.8.5")
-    implementation ("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.1")
+    implementation(libs.okhttp)
+    implementation (libs.kotlinx.coroutines.android)
+    implementation (libs.gson)
+    implementation (libs.jackson.module.kotlin)
 
 
 }

+ 10 - 0
App/app/src/main/java/com/example/mystictale/Constants/SupabaseConnect.kt

@@ -17,4 +17,14 @@ object SupabaseConnect {
         }
         install(Storage)
     }
+    val supabaseAdmin = createSupabaseClient(
+        supabaseUrl = "https://eykhnnlgofgxdzlixydt.supabase.co",
+        supabaseKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV5a2hubmxnb2ZneGR6bGl4eWR0Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcyOTIzNDg3OCwiZXhwIjoyMDQ0ODEwODc4fQ.Y_4IElNlvVo59iYJ4Wa9AJyP0wT7z3ysB50vxzL9bQU"
+    ) {
+        install(Auth)
+        install(Postgrest){
+            propertyConversionMethod = PropertyConversionMethod.SERIAL_NAME
+        }
+        install(Storage)
+    }
 }

+ 0 - 67
App/app/src/main/java/com/example/mystictale/MainActivity.kt

@@ -6,17 +6,8 @@ import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
 import androidx.annotation.RequiresApi
-import com.example.example.ExampleJson2KtKotlin
 import com.example.mystictale.navigation.Navigation
 import com.example.mystictale.ui.theme.MysticTaleTheme
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.OkHttpClient
-import okhttp3.Request
 
 
 class MainActivity : ComponentActivity() {
@@ -27,70 +18,12 @@ class MainActivity : ComponentActivity() {
         enableEdgeToEdge()
         setContent {
             MysticTaleTheme {
-
-
                 Navigation()
-//                getUserIdByEmail("kbobarik@mail.ru") { userId ->
-//                    if (userId != null) {
-//                        println("UID пользователя: $userId")
-//                    } else {
-//                        println("Пользователь с таким email не найден.")
-//                    }
-//                }
-
-
             }
         }
     }
 }
 
-fun getUserIdByEmail(email: String, onResult: (String?) -> Unit) {
-    CoroutineScope(Dispatchers.IO).launch {
-        val client = OkHttpClient()
-        val url = "https://eykhnnlgofgxdzlixydt.supabase.co/auth/v1/admin/users?filter=email.eq.$email"
-        val request = Request.Builder()
-            .url(url)
-            .addHeader(
-                "Authorization",
-                "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV5a2hubmxnb2ZneGR6bGl4eWR0Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcyOTIzNDg3OCwiZXhwIjoyMDQ0ODEwODc4fQ.Y_4IElNlvVo59iYJ4Wa9AJyP0wT7z3ysB50vxzL9bQU"
-            ) // Добавьте ваш service_role ключ
-            .addHeader(
-                "apikey",
-                "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV5a2hubmxnb2ZneGR6bGl4eWR0Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcyOTIzNDg3OCwiZXhwIjoyMDQ0ODEwODc4fQ.Y_4IElNlvVo59iYJ4Wa9AJyP0wT7z3ysB50vxzL9bQU"
-            ) // То же самое
-            .build()
-
-        try {
-            val response = client.newCall(request).execute()
-            val responseBody = response.body?.string()
-
-            // Обработка кода ошибки
-            if (response.code != 200) {
-                println("Ошибка: ${response.code}, Сообщение: $responseBody")
-                withContext(Dispatchers.Main) {
-                    onResult(null)
-                }
-                return@launch
-            }
 
-            val userId = if (!responseBody.isNullOrEmpty()) {
-                val mapper = jacksonObjectMapper()
-                val userFromJson = mapper.readValue<List<ExampleJson2KtKotlin>>(responseBody)
-                if (userFromJson.isNotEmpty()) {
-                    val userObject = userFromJson;
-                } else null
-            } else null
-
-            withContext(Dispatchers.Main) {
-                onResult("1")
-            }
-        } catch (e: Exception) {
-            e.printStackTrace()
-            withContext(Dispatchers.Main) {
-                onResult(null)
-            }
-        }
-    }
-}
 
 

+ 179 - 0
App/app/src/main/java/com/example/mystictale/Screen/Profile.kt

@@ -0,0 +1,179 @@
+package com.example.mystictale.Screen
+
+import androidx.compose.foundation.Image
+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.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.paint
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import com.example.mystictale.R
+import com.example.mystictale.ViewModels.AuthViewModel
+import com.example.mystictale.models.Users
+import com.example.mystictale.resources.components.Loading
+import com.example.mystictale.resources.components.ProfileTextField
+import com.example.mystictale.ui.theme.Grey
+import com.example.mystictale.ui.theme.OpenSans
+
+@Composable
+fun Profile(navController: NavController) {
+    val viewModel = AuthViewModel()
+    val user by viewModel.user
+    val focusManager = LocalFocusManager.current
+    val keyboardController = LocalSoftwareKeyboardController.current
+    val isEnabled = remember { mutableStateOf(false) }
+    val flagName = remember { mutableStateOf(false) }
+    val flag = remember { mutableStateOf(true) }
+    if (flag.value) {
+        viewModel.selectProfile()
+        flag.value = false
+    }
+    if (user.isNotEmpty()) {
+        val name = remember {
+            mutableStateOf(user.last().name)
+        }
+
+        val date_of_birth = remember {
+            mutableStateOf(user.last().date_of_birth)
+        }
+        val gender = remember {
+            mutableStateOf("")
+        }
+        if(user.last().id_gender == 1){
+            gender.value = "Женский"
+        }else{
+            gender.value = "Мужской"
+        }
+        Column(
+            Modifier
+                .fillMaxSize()
+                .paint(
+                    painterResource(id = R.drawable.background),
+                    contentScale = ContentScale.FillBounds
+                )
+                .pointerInput(Unit) {
+                    detectTapGestures(onTap = {
+                        keyboardController?.hide()
+                        focusManager.clearFocus()
+                    })
+                }
+                .padding(10.dp)
+                .padding(top = 30.dp),
+            verticalArrangement = Arrangement.Top,
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            Text(
+                text = "Профиль",
+                fontFamily = OpenSans,
+                fontWeight = FontWeight.Bold,
+                fontSize = 40.sp,
+                color = Color.White
+            )
+            Spacer(modifier = Modifier.height(20.dp))
+            Image(painter = painterResource(id = R.drawable.girl), contentDescription = "")
+            Spacer(modifier = Modifier.height(20.dp))
+            Column(
+                Modifier
+                    .fillMaxWidth()
+                    .padding(horizontal = 20.dp)
+            ) {
+                Text(
+                    text = "Имя",
+                    fontFamily = OpenSans,
+                    fontWeight = FontWeight.Bold,
+                    fontSize = 14.sp,
+                    color = Grey
+                )
+                Spacer(modifier = Modifier.height(10.dp))
+                ProfileTextField(
+                    value = name.value,
+                    onValue = { name.value = it }, placeholder = "Имя",
+                    keyboardType = KeyboardType.Text,
+                    isEnable = isEnabled.value,
+                    flag = flagName.value
+                )
+            }
+            Spacer(modifier = Modifier.height(15.dp))
+            Column(
+                Modifier
+                    .fillMaxWidth()
+                    .padding(horizontal = 20.dp)
+            ) {
+                Text(
+                    text = "Дата рождения",
+                    fontFamily = OpenSans,
+                    fontWeight = FontWeight.Bold,
+                    fontSize = 14.sp,
+                    color = Grey
+                )
+                Spacer(modifier = Modifier.height(10.dp))
+                ProfileTextField(
+                    value = date_of_birth.value,
+                    onValue = { date_of_birth.value = it },
+                    placeholder = "Дата рождения",
+                    keyboardType = KeyboardType.Text,
+                    isEnable = isEnabled.value,
+                    flag = flagName.value
+                )
+            }
+            Spacer(modifier = Modifier.height(15.dp))
+            Column(
+                Modifier
+                    .fillMaxWidth()
+                    .padding(horizontal = 20.dp)
+            ) {
+                Text(
+                    text = "Пол",
+                    fontFamily = OpenSans,
+                    fontWeight = FontWeight.Bold,
+                    fontSize = 14.sp,
+                    color = Grey
+                )
+                Spacer(modifier = Modifier.height(10.dp))
+                ProfileTextField(
+                    value = gender.value,
+                    onValue = { gender.value = it },
+                    placeholder = "Дата рождения",
+                    keyboardType = KeyboardType.Text,
+                    isEnable = isEnabled.value,
+                    flag = flagName.value
+                )
+            }
+        }
+    } else {
+        Box(
+            Modifier
+                .fillMaxSize()
+                .paint(
+                    painterResource(id = R.drawable.background),
+                    contentScale = ContentScale.FillBounds
+                )
+        ) {
+            Loading()
+        }
+    }
+
+}

+ 72 - 10
App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/NewPassword.kt

@@ -34,6 +34,7 @@ import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.core.text.isDigitsOnly
 import androidx.navigation.NavController
 import com.example.mystictale.R
 import com.example.mystictale.ViewModels.AuthViewModel
@@ -41,6 +42,7 @@ import com.example.mystictale.models.UserState
 import com.example.mystictale.navigation.Screens
 import com.example.mystictale.resources.components.Loading
 import com.example.mystictale.resources.components.PasswordTextField
+import com.example.mystictale.resources.components.ValidationPassword
 import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.OpenSans
 
@@ -60,6 +62,7 @@ fun NewPassword(navController: NavController, viewModel: AuthViewModel) {
     val flag = remember {
         mutableStateOf(false)
     }
+    val passwordFlag = remember { mutableStateOf(false) }
     Column(
         Modifier
             .fillMaxSize()
@@ -104,8 +107,12 @@ fun NewPassword(navController: NavController, viewModel: AuthViewModel) {
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
-                Spacer(modifier = Modifier.height(30.dp))
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
+                Spacer(modifier = Modifier.height(10.dp))
                 Text(
                     text = "Придумайте новый пароль",
                     fontWeight = FontWeight.Bold,
@@ -113,15 +120,17 @@ fun NewPassword(navController: NavController, viewModel: AuthViewModel) {
                     fontSize = 24.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(start = 30.dp),
+                        .fillMaxWidth(),
                     style = MaterialTheme.typography.headlineMedium
                 )
                 Spacer(modifier = Modifier.height(30.dp))
 
                 PasswordTextField(
                     value = password.value,
-                    onValueChange = { password.value = it },
+                    onValueChange = {
+                        password.value = it
+                        passwordFlag.value = false
+                    },
                     placeholder = "Пароль",
                     false
                 )
@@ -129,20 +138,73 @@ fun NewPassword(navController: NavController, viewModel: AuthViewModel) {
 
                 PasswordTextField(
                     value = repeatedPassword.value,
-                    onValueChange = { repeatedPassword.value = it },
+                    onValueChange = {
+                        repeatedPassword.value = it
+                        passwordFlag.value = false
+                    },
                     placeholder = "Повторный пароль", false
                 )
+
+                if (passwordFlag.value) {
+                    if (password.value.isEmpty()) {
+                        Text(
+                            "Введите пароль",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (password.value.length < 6) {
+                        Text(
+                            "Пароль содержит меньше 6 символов",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (password.value.isDigitsOnly()) {
+                        Text(
+                            "Пароль не содержит букв",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (!password.value.any { it.isDigit() }) {
+                        Text(
+                            "Пароль не содержит цифр",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (password.value != repeatedPassword.value) {
+                        Text(
+                            "Пароли не совпадают",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    }
+                }
             }
         }
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.resetPassword(passwordUser = password.value)
-                    flag.value = true
+                    if (!ValidationPassword(password.value, repeatedPassword.value)) {
+                        viewModel.resetPassword(passwordUser = password.value)
+                        flag.value = true
+                    } else {
+                        passwordFlag.value = true
+                    }
+
                 },
                 modifier = Modifier
-                    .width(310.dp)
-                    .height(48.dp),
+                    .fillMaxWidth()
+                    .height(48.dp)
+                    .padding(horizontal = 30.dp),
                 shape = RoundedCornerShape(12.dp),
                 colors = ButtonColors(
                     containerColor = DarkPurple,

+ 45 - 27
App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/PasswordRecovery.kt

@@ -1,5 +1,6 @@
 package com.example.mystictale.Screen.passwordRecovery
 
+import android.util.Patterns
 import android.widget.Toast
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.gestures.detectTapGestures
@@ -19,7 +20,6 @@ import androidx.compose.material3.ButtonColors
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
@@ -39,16 +39,18 @@ import androidx.compose.ui.unit.sp
 import androidx.navigation.NavController
 import com.example.mystictale.R
 import com.example.mystictale.ViewModels.AuthViewModel
-import com.example.mystictale.models.UserState
 import com.example.mystictale.navigation.Screens
 import com.example.mystictale.resources.components.GenericTextField
 import com.example.mystictale.resources.components.Loading
+import com.example.mystictale.resources.getUserIdByEmail
 import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.OpenSans
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 @Composable
-fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
-    val userState by viewModel.userState
+fun PasswordRecovery(navController: NavController, viewModel: AuthViewModel) {
     val focusManager = LocalFocusManager.current
     val context = LocalContext.current
     val keyboardController = LocalSoftwareKeyboardController.current
@@ -58,6 +60,7 @@ fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
     val flag = remember {
         mutableStateOf(false)
     }
+    val emailFlag = remember { mutableStateOf(false) }
     Column(
         Modifier
             .fillMaxSize()
@@ -104,10 +107,11 @@ fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
                 }
             }
             Column(
-                modifier = Modifier.padding(20.dp)
+                modifier = Modifier
+                    .padding(20.dp)
                     .padding(start = 15.dp, end = 5.dp)
             ) {
-                Spacer(modifier = Modifier.height(30.dp))
+                Spacer(modifier = Modifier.height(10.dp))
                 Text(
                     text = "Сброс пароля",
                     fontWeight = FontWeight.Bold,
@@ -134,12 +138,25 @@ fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
 
                 GenericTextField(
                     email.value,
-                    { email.value = it },
+                    {
+                        email.value = it
+                        emailFlag.value = false
+                    },
                     "E-mail",
                     KeyboardType.Email,
-                    false
+                    emailFlag.value
                 )
 
+                if (emailFlag.value) {
+                    Text(
+                        "Неверно введена почта",
+                        fontWeight = FontWeight.Light,
+                        fontFamily = OpenSans,
+                        fontSize = 13.sp,
+                        color = Color.Red
+                    )
+                }
+
             }
 
         }
@@ -147,8 +164,25 @@ fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.getUserIdByEmail(email.value)
-                    flag.value = true },
+                    if (Patterns.EMAIL_ADDRESS.matcher(email.value).matches()) {
+                        CoroutineScope(Dispatchers.Main).launch {
+                            flag.value = true
+                            val userId = getUserIdByEmail(email.value)
+                            if (userId != null) {
+                                viewModel.uid = userId
+                                flag.value = false
+                                navController.navigate(Screens.NewPassword.route)
+                            } else {
+                                flag.value = false
+                                Toast.makeText(context, "Аккаунт не найден", Toast.LENGTH_SHORT)
+                                    .show()
+                            }
+                        }
+                    } else {
+                        emailFlag.value = true
+                    }
+
+                },
                 modifier = Modifier
                     .fillMaxWidth()
                     .height(48.dp)
@@ -170,22 +204,6 @@ fun PasswordRecovery(navController: NavController,viewModel: AuthViewModel) {
 
     }
     if (flag.value) {
-        when (userState) {
-            is UserState.Loading -> {
-                Loading()
-            }
-
-            is UserState.Success -> {
-                navController.navigate(Screens.NewPassword.route)
-                flag.value = false
-            }
-
-            is UserState.Error -> {
-                val message = (userState as UserState.Error).message
-                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
-                flag.value = false
-            }
-
-        }
+        Loading()
     }
 }

+ 3 - 4
App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationDateOfBirth.kt

@@ -44,6 +44,7 @@ import com.example.mystictale.R
 import com.example.mystictale.ViewModels.AuthViewModel
 import com.example.mystictale.navigation.Screens
 import com.example.mystictale.resources.components.dateComponents.DateOfBirthTextField
+import com.example.mystictale.resources.components.dateComponents.FormattingDateForDatabase
 import com.example.mystictale.resources.components.dateComponents.ValidationDate
 import com.example.mystictale.resources.components.dateComponents.isDateValid
 import com.example.mystictale.ui.theme.DarkPurple
@@ -64,15 +65,13 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
     val formattedDate by remember {
         derivedStateOf { DateTimeFormatter.ofPattern("ddMMyyyy").format(pickedDate) }
     }
-    val formattedDateFromBase by remember {
-        derivedStateOf { DateTimeFormatter.ofPattern("yyyy-MM-dd").format(pickedDate) }
-    }
     val dateDialogState = rememberMaterialDialogState()
     val dateOfBirth = remember {
         mutableStateOf("")
     }
     val dateFlag = remember { mutableStateOf(false) }
     val formatter = DateTimeFormatter.ofPattern("ddMMyyyy")
+    val formatterFoeBase = DateTimeFormatter.ofPattern("yyyy-MM-dd")
     Column(
         Modifier
             .fillMaxSize()
@@ -206,7 +205,7 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
                     if (ValidationDate(dateOfBirth.value, formatter)) {
                         dateFlag.value = true
                     } else {
-                        viewModel.dateOfBirth = formattedDateFromBase
+                        viewModel.dateOfBirth = FormattingDateForDatabase(dateOfBirth.value)
                         navController.navigate(Screens.RegistrationGender.route)
                     }
                 },

+ 21 - 1
App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationGender.kt

@@ -48,6 +48,7 @@ import com.example.mystictale.ui.theme.OpenSans
 fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
     val userState by viewModel.userState
     val flag = remember { mutableStateOf(false) }
+    val flag2 = remember { mutableStateOf(false) }
     val genderFlag = remember { mutableStateOf(false) }
 
     val context = LocalContext.current
@@ -174,7 +175,8 @@ fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
             }
 
             is UserState.Success -> {
-                navController.navigate(Screens.Start.route)
+                viewModel.addProfile()
+                flag2.value = true
                 flag.value = false
             }
 
@@ -185,5 +187,23 @@ fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
             }
         }
     }
+    if (flag2.value) {
+        when (userState) {
+            is UserState.Loading -> {
+                Loading()
+            }
+
+            is UserState.Success -> {
+                navController.navigate(Screens.Start.route)
+                flag2.value = false
+            }
+
+            is UserState.Error -> {
+                val message = (userState as UserState.Error).message
+                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
+                flag2.value = false
+            }
+        }
+    }
 
 }

+ 2 - 2
App/app/src/main/java/com/example/mystictale/Screen/signIn/SignIn.kt

@@ -118,7 +118,7 @@ fun SignIn(navController: NavController, viewModel: AuthViewModel) {
                     .padding(20.dp)
                     .padding(start = 15.dp, end = 5.dp)
             ) {
-                Spacer(modifier = Modifier.height(30.dp))
+                Spacer(modifier = Modifier.height(10.dp))
                 Text(
                     text = "Авторизация",
                     fontWeight = FontWeight.Bold,
@@ -242,7 +242,7 @@ fun SignIn(navController: NavController, viewModel: AuthViewModel) {
             }
 
             is UserState.Success -> {
-                navController.navigate(Screens.Start.route)
+                navController.navigate(Screens.Profile.route)
                 flag.value = false
             }
 

+ 51 - 31
App/app/src/main/java/com/example/mystictale/ViewModels/AuthViewModel.kt

@@ -10,28 +10,24 @@ import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.example.mystictale.Constants.SupabaseConnect
 import com.example.mystictale.models.UserState
+import com.example.mystictale.models.Users
 import com.example.mystictale.resources.SharedPreferenceHelper
 import io.github.jan.supabase.auth.auth
 import io.github.jan.supabase.auth.providers.builtin.Email
-import io.github.jan.supabase.postgrest.postgrest
-import io.github.jan.supabase.postgrest.rpc
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
+import io.github.jan.supabase.postgrest.from
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import org.json.JSONObject
 
 class AuthViewModel : ViewModel() {
     private val _userState = mutableStateOf<UserState>(UserState.Loading)
     val userState: State<UserState> = _userState
-    private var uid by mutableStateOf<String?>(null)
+    var uid by mutableStateOf<String?>(null)
     var emailUser by mutableStateOf<String?>(null)
     var passwordUser by mutableStateOf<String?>(null)
     var dateOfBirth by mutableStateOf<String?>(null)
     var gender by mutableStateOf<Int?>(null)
     var name by mutableStateOf<String?>(null)
+    private val _user = mutableStateOf(listOf<Users>())
+    val user: State<List<Users>> = _user
     fun onSignUpEmailPassword(context: Context) {
         viewModelScope.launch {
             try {
@@ -74,15 +70,56 @@ class AuthViewModel : ViewModel() {
         }
     }
 
-    fun resetPassword(passwordUser: String){
+    fun addProfile() {
+        viewModelScope.launch {
+            try {
+                _userState.value = UserState.Loading
+                SupabaseConnect.supabase.from("Users").insert(
+                    Users(
+                        name = name!!,
+                        id_gender = gender!!,
+                        UID = SupabaseConnect.supabase.auth.currentUserOrNull()!!.id,
+                        date_of_birth = dateOfBirth!!
+                    )
+                )
+
+                _userState.value = UserState.Success("Success create profile")
+                Log.d("my_tag", "Success create profile")
+
+            } catch (e: Exception) {
+                _userState.value = UserState.Error("Error: ${e.message}")
+                Log.d("my_tag", e.message!!)
+            }
+        }
+    }
+
+    fun selectProfile() {
+        viewModelScope.launch {
+            try {
+                _userState.value = UserState.Loading
+                _user.value =  SupabaseConnect.supabase.from("Users").select {
+                    filter {
+                        Users::UID eq SupabaseConnect.supabase.auth.currentUserOrNull()!!.id
+                    }
+                }.decodeList<Users>()
+
+                _userState.value = UserState.Success("Success create profile")
+                Log.d("my_tag", "Success create profile")
+
+            } catch (e: Exception) {
+                _userState.value = UserState.Error("Error: ${e.message}")
+                Log.d("my_tag", e.message!!)
+            }
+        }
+    }
+
+    fun resetPassword(passwordUser: String) {
         viewModelScope.launch {
             try {
                 Log.d("my_tag", uid!!)
                 _userState.value = UserState.Loading
-                SupabaseConnect.supabase.auth.admin.updateUserById(
-                    uid!!
-                ){
-                    mapOf("password" to passwordUser)
+                SupabaseConnect.supabaseAdmin.auth.admin.updateUserById(uid = uid!!) {
+                    password = passwordUser
                 }
                 _userState.value = UserState.Success("Success changed password")
                 Log.d("my_tag", "Success changed password")
@@ -109,21 +146,4 @@ class AuthViewModel : ViewModel() {
 
     }
 
-    fun getUserIdByEmail(email: String) {
-        viewModelScope.launch {
-            try {
-                _userState.value = UserState.Loading
-                uid = SupabaseConnect.supabase.postgrest.rpc("get_user_id_by_email", email).toString()
-                Log.d("my_tag", uid!!)
-                _userState.value = UserState.Success("Success reset password")
-                Log.d("my_tag", "Success reset password")
-
-            } catch (e: Exception) {
-                _userState.value = UserState.Error("Error: ${e.message}")
-                Log.d("my_tag", e.message!!)
-            }
-        }
-    }
-
-
 }

+ 0 - 12
App/app/src/main/java/com/example/mystictale/models/AppMetadata.kt

@@ -1,12 +0,0 @@
-package com.example.example
-
-import com.google.gson.annotations.SerializedName
-
-
-data class AppMetadata (
-  @SerializedName("provider")
-  var provider  : String? = null,
-  @SerializedName("providers" )
-  var providers : ArrayList<String> = arrayListOf()
-
-)

+ 0 - 11
App/app/src/main/java/com/example/mystictale/models/ExampleJson2KtKotlin.kt

@@ -1,11 +0,0 @@
-package com.example.example
-
-import com.google.gson.annotations.SerializedName
-
-
-data class ExampleJson2KtKotlin (
-
-  @SerializedName("users" ) var users : ArrayList<Users> = arrayListOf(),
-  @SerializedName("aud"   ) var aud   : String?          = null
-
-)

+ 0 - 13
App/app/src/main/java/com/example/mystictale/models/UserMetadata.kt

@@ -1,13 +0,0 @@
-package com.example.example
-
-import com.google.gson.annotations.SerializedName
-
-
-data class UserMetadata (
-
-  @SerializedName("email"          ) var email         : String?  = null,
-  @SerializedName("email_verified" ) var emailVerified : Boolean? = null,
-  @SerializedName("phone_verified" ) var phoneVerified : Boolean? = null,
-  @SerializedName("sub"            ) var sub           : String?  = null
-
-)

+ 15 - 20
App/app/src/main/java/com/example/mystictale/models/Users.kt

@@ -1,23 +1,18 @@
-package com.example.example
+package com.example.mystictale.models
 
-import com.google.gson.annotations.SerializedName
-
-
-data class Users (
-
-  @SerializedName("id"                 ) var id               : String?       = null,
-  @SerializedName("aud"                ) var aud              : String?       = null,
-  @SerializedName("role"               ) var role             : String?       = null,
-  @SerializedName("email"              ) var email            : String?       = null,
-  @SerializedName("email_confirmed_at" ) var emailConfirmedAt : String?       = null,
-  @SerializedName("phone"              ) var phone            : String?       = null,
-  @SerializedName("confirmed_at"       ) var confirmedAt      : String?       = null,
-  @SerializedName("last_sign_in_at"    ) var lastSignInAt     : String?       = null,
-  @SerializedName("app_metadata"       ) var appMetadata      : AppMetadata?  = AppMetadata(),
-  @SerializedName("user_metadata"      ) var userMetadata     : UserMetadata? = UserMetadata(),
-  @SerializedName("identities"         ) var identities       : String?       = null,
-  @SerializedName("created_at"         ) var createdAt        : String?       = null,
-  @SerializedName("updated_at"         ) var updatedAt        : String?       = null,
-  @SerializedName("is_anonymous"       ) var isAnonymous      : Boolean?      = null
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
 
+@Serializable
+data class Users(
+    val id: Int? = 0,
+    @SerialName("Name")
+    val name: String,
+    @SerialName("Date_of_birth")
+    val date_of_birth: String,
+    @SerialName("Id_gender")
+    val id_gender: Int,
+    @SerialName("Avatar")
+    val avatar: String? = null,
+    val UID: String
 )

+ 5 - 0
App/app/src/main/java/com/example/mystictale/navigation/Navigation.kt

@@ -7,6 +7,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.compose.NavHost
 import androidx.navigation.compose.composable
 import androidx.navigation.compose.rememberNavController
+import com.example.mystictale.Screen.Profile
 import com.example.mystictale.Screen.registration.RegistrationDateOfBirth
 import com.example.mystictale.Screen.registration.RegistrationEmail
 import com.example.mystictale.Screen.registration.RegistrationGender
@@ -61,6 +62,10 @@ fun Navigation() {
         {
             NewPassword(navController,viewModel)
         }
+        composable(Screens.Profile.route)
+        {
+            Profile(navController)
+        }
 
     }
 }

+ 1 - 0
App/app/src/main/java/com/example/mystictale/navigation/Screens.kt

@@ -10,5 +10,6 @@ sealed class Screens (val route:String){
     object SingIn: Screens("sign_in")
     object PasswordRecovery: Screens("password_recovery")
     object NewPassword: Screens("new_password")
+    object Profile: Screens("profile")
 
 }

+ 50 - 0
App/app/src/main/java/com/example/mystictale/resources/GetUserByEmail.kt

@@ -0,0 +1,50 @@
+package com.example.mystictale.resources
+
+import kotlinx.coroutines.*
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import org.json.JSONObject
+
+suspend fun getUserIdByEmail(emailUser: String): String? = withContext(Dispatchers.IO) {
+    val client = OkHttpClient()
+    val url = "https://eykhnnlgofgxdzlixydt.supabase.co/auth/v1/admin/users"
+    val request = Request.Builder()
+        .url(url)
+        .addHeader(
+            "Authorization",
+            "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV5a2hubmxnb2ZneGR6bGl4eWR0Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcyOTIzNDg3OCwiZXhwIjoyMDQ0ODEwODc4fQ.Y_4IElNlvVo59iYJ4Wa9AJyP0wT7z3ysB50vxzL9bQU"
+        )
+        .addHeader(
+            "apikey",
+            "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV5a2hubmxnb2ZneGR6bGl4eWR0Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcyOTIzNDg3OCwiZXhwIjoyMDQ0ODEwODc4fQ.Y_4IElNlvVo59iYJ4Wa9AJyP0wT7z3ysB50vxzL9bQU"
+        )
+        .build()
+
+    try {
+        val response = client.newCall(request).execute()
+        val responseBody = response.body?.string()
+
+        // Проверяем код ответа
+        if (response.code != 200 || responseBody.isNullOrEmpty()) {
+            println("Ошибка: ${response.code}, Сообщение: $responseBody")
+            return@withContext null
+        }
+
+        // Обрабатываем JSON-ответ
+        val jsonResponse = JSONObject(responseBody)
+        val usersArray = jsonResponse.optJSONArray("users") ?: return@withContext null
+
+        for (i in 0 until usersArray.length()) {
+            val user = usersArray.getJSONObject(i)
+            val email = user.optString("email")
+            if (email == emailUser) {
+                return@withContext user.optString("id")
+            }
+        }
+
+        return@withContext null // Если email не найден
+    } catch (e: Exception) {
+        e.printStackTrace()
+        return@withContext null
+    }
+}

+ 7 - 5
App/app/src/main/java/com/example/mystictale/resources/components/GenericTextField.kt

@@ -12,6 +12,8 @@ import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.unit.sp
+import com.example.mystictale.ui.theme.DarkPurple
+import com.example.mystictale.ui.theme.Grey
 import com.example.mystictale.ui.theme.OpenSans
 
 @Composable
@@ -32,16 +34,16 @@ fun GenericTextField(
         ),
         colors = TextFieldDefaults.colors(
             unfocusedTextColor = Color.White,
-            unfocusedPlaceholderColor = Color(0xffA1A0A3),
+            unfocusedPlaceholderColor = Grey,
             unfocusedContainerColor = Color.Transparent,
             focusedTextColor = Color.White,
             focusedContainerColor = Color.Transparent,
-            focusedPlaceholderColor = Color(0xffA1A0A3),
-            focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B),
+            focusedPlaceholderColor = Grey,
+            focusedIndicatorColor = DarkPurple,
+            unfocusedIndicatorColor = DarkPurple,
             errorContainerColor = Color.Transparent,
             errorTextColor = Color.White,
-            errorPlaceholderColor = Color(0xffA1A0A3),
+            errorPlaceholderColor = Grey,
         ),
         isError = flag,
         placeholder = { Text(text = placeholder) },

+ 7 - 5
App/app/src/main/java/com/example/mystictale/resources/components/PasswordTextField.kt

@@ -22,6 +22,8 @@ import androidx.compose.ui.text.input.VisualTransformation
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import com.example.mystictale.R
+import com.example.mystictale.ui.theme.DarkPurple
+import com.example.mystictale.ui.theme.Grey
 import com.example.mystictale.ui.theme.OpenSans
 
 @Composable
@@ -60,16 +62,16 @@ fun PasswordTextField(
         visualTransformation = if (checked.value) VisualTransformation.None else PasswordVisualTransformation(),
         colors = TextFieldDefaults.colors(
             unfocusedTextColor = Color.White,
-            unfocusedPlaceholderColor = Color(0xffA1A0A3),
+            unfocusedPlaceholderColor = Grey,
             unfocusedContainerColor = Color.Transparent,
             focusedTextColor = Color.White,
             focusedContainerColor = Color.Transparent,
-            focusedPlaceholderColor = Color(0xffA1A0A3),
-            focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B),
+            focusedPlaceholderColor = Grey ,
+            focusedIndicatorColor = DarkPurple,
+            unfocusedIndicatorColor = DarkPurple,
             errorContainerColor = Color.Transparent,
             errorTextColor = Color.White,
-            errorPlaceholderColor = Color(0xffA1A0A3),
+            errorPlaceholderColor = Grey,
         ),
         placeholder = { Text(text = placeholder) },
         maxLines = 1,

+ 80 - 0
App/app/src/main/java/com/example/mystictale/resources/components/ProfileTextField.kt

@@ -0,0 +1,80 @@
+package com.example.mystictale.resources.components
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.example.mystictale.ui.theme.DarkPurple
+import com.example.mystictale.ui.theme.Grey
+import com.example.mystictale.ui.theme.OpenSans
+
+@Composable
+fun ProfileTextField(
+    value: String,
+    onValue: (String) -> Unit,
+    placeholder: String,
+    keyboardType: KeyboardType,
+    flag: Boolean,
+    isEnable: Boolean
+) {
+    OutlinedTextField(
+        value = value,
+        onValueChange = onValue,
+        singleLine = true,
+        keyboardOptions = KeyboardOptions(
+            keyboardType = keyboardType,
+            imeAction = ImeAction.Done
+        ),
+        shape = RoundedCornerShape(10.dp),
+        colors = TextFieldDefaults.colors(
+            unfocusedTextColor = Color.White,
+            unfocusedPlaceholderColor = Grey,
+            unfocusedContainerColor = DarkPurple,
+            focusedTextColor = Color.White,
+            focusedContainerColor = DarkPurple,
+            focusedPlaceholderColor = Color.White,
+            focusedIndicatorColor = Color.Transparent,
+            unfocusedIndicatorColor = Color.Transparent,
+            errorContainerColor = DarkPurple,
+            errorTextColor = Color.White,
+            errorPlaceholderColor = Color.White,
+            disabledTextColor = Color.White,
+            disabledContainerColor = DarkPurple,
+            disabledPlaceholderColor = Color.White
+        ),
+        isError = flag,
+
+        placeholder = {
+            Text(
+                text = placeholder,
+                fontFamily = OpenSans,
+                fontWeight = FontWeight.Normal,
+                fontSize = 14.sp,
+            )
+        },
+        maxLines = 1,
+        textStyle = TextStyle(
+            fontFamily = OpenSans,
+            fontWeight = FontWeight.Normal,
+            fontSize = 14.sp,
+        ),
+        enabled = isEnable,
+        modifier = Modifier
+            .fillMaxWidth()
+            .height(52.dp)
+
+
+    )
+}

+ 7 - 5
App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/DateOfBirthTextField.kt

@@ -19,6 +19,8 @@ import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import com.example.mystictale.ui.theme.DarkPurple
+import com.example.mystictale.ui.theme.Grey
 import com.example.mystictale.ui.theme.OpenSans
 import com.vanpra.composematerialdialogs.MaterialDialogState
 
@@ -41,16 +43,16 @@ fun DateOfBirthTextField(
 
         colors = TextFieldDefaults.colors(
             unfocusedTextColor = Color.White,
-            unfocusedPlaceholderColor = Color(0xffA1A0A3),
+            unfocusedPlaceholderColor = Grey,
             unfocusedContainerColor = Color.Transparent,
             focusedTextColor = Color.White,
             focusedContainerColor = Color.Transparent,
-            focusedPlaceholderColor = Color(0xffA1A0A3),
-            focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B),
+            focusedPlaceholderColor = Grey,
+            focusedIndicatorColor = DarkPurple,
+            unfocusedIndicatorColor = DarkPurple,
             errorContainerColor = Color.Transparent,
             errorTextColor = Color.White,
-            errorPlaceholderColor = Color(0xffA1A0A3),
+            errorPlaceholderColor = Grey,
         ),
         isError = flag,
         trailingIcon = {

+ 22 - 0
App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/FormattingDateForDatabase.kt

@@ -0,0 +1,22 @@
+package com.example.mystictale.resources.components.dateComponents
+
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+
+fun FormattingDateForDatabase(inputDate: String): String? {
+    return try {
+        // Формат входной даты
+        val inputFormat = SimpleDateFormat("ddMMyyyy", Locale.getDefault())
+        // Формат выходной даты
+        val outputFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+
+        // Парсинг входной строки в дату
+        val date = inputFormat.parse(inputDate)
+        // Преобразование даты в строку нужного формата
+        outputFormat.format(date!!)
+    } catch (e: Exception) {
+        // Если возникнет ошибка, возвращаем null
+        null
+    }
+}

TEMPAT SAMPAH
App/app/src/main/res/drawable/girl.png


+ 2 - 1
App/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.22"
+    kotlin("jvm") version "1.4.21"
+
 }

+ 8 - 0
App/gradle/libs.versions.toml

@@ -2,12 +2,15 @@
 agp = "8.5.1"
 bom = "3.0.2"
 fragmentKtx = "1.8.5"
+gson = "2.10.1"
+jacksonModuleKotlin = "2.12.1"
 kotlin = "2.0.0"
 datetime = "0.8.1-rc"
 coreKtx = "1.13.1"
 junit = "4.13.2"
 junitVersion = "1.2.1"
 espressoCore = "3.6.1"
+kotlinxCoroutinesAndroid = "1.8.1"
 ktorClientOkhttp = "3.0.0-rc-1"
 lifecycleRuntimeKtx = "2.8.5"
 activityCompose = "1.9.2"
@@ -15,6 +18,7 @@ composeBom = "2024.04.01"
 lifecycleViewmodelKtx = "2.8.7"
 material3 = "1.4.0-alpha03"
 navigationCompose = "2.8.0"
+okhttp = "4.12.0"
 
 [libraries]
 androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -23,6 +27,8 @@ androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-
 androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
 auth-kt = { module = "io.github.jan-tennert.supabase:auth-kt" }
 bom = { module = "io.github.jan-tennert.supabase:bom", version.ref = "bom" }
+gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
+jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jacksonModuleKotlin" }
 junit = { group = "junit", name = "junit", version.ref = "junit" }
 datetime = { module = "io.github.vanpra.compose-material-dialogs:datetime", version.ref = "datetime" }
 androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
@@ -37,8 +43,10 @@ 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-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" }
 ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktorClientOkhttp" }
 material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
+okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
 storage-kt = { module = "io.github.jan-tennert.supabase:storage-kt", version.ref = "bom" }
 
 androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }