Parcourir la source

app: update layout. add validatuion fields

Bobarik31p il y a 1 semaine
Parent
commit
522b91a5f7
20 fichiers modifiés avec 419 ajouts et 117 suppressions
  1. 8 0
      App/.idea/deploymentTargetSelector.xml
  2. 2 0
      App/app/src/main/java/com/example/mystictale/MainActivity.kt
  3. 2 0
      App/app/src/main/java/com/example/mystictale/Screen/Start.kt
  4. 3 2
      App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/NewPassword.kt
  5. 7 1
      App/app/src/main/java/com/example/mystictale/Screen/passwordRecovery/PasswordRecovery.kt
  6. 63 9
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationDateOfBirth.kt
  7. 38 9
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationEmail.kt
  8. 33 10
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationGender.kt
  9. 31 8
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationName.kt
  10. 71 11
      App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationPassword.kt
  11. 9 3
      App/app/src/main/java/com/example/mystictale/Screen/signIn/SignIn.kt
  12. 4 4
      App/app/src/main/java/com/example/mystictale/ViewModels/AuthViewModel.kt
  13. 24 41
      App/app/src/main/java/com/example/mystictale/resources/components/ChooseGender.kt
  14. 14 7
      App/app/src/main/java/com/example/mystictale/resources/components/GenericTextField.kt
  15. 22 0
      App/app/src/main/java/com/example/mystictale/resources/components/Loading.kt
  16. 13 5
      App/app/src/main/java/com/example/mystictale/resources/components/PasswordTextField.kt
  17. 13 1
      App/app/src/main/java/com/example/mystictale/resources/components/ValidationPassword.kt
  18. 14 5
      App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/DateOfBirthTextField.kt
  19. 21 1
      App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/ValidationDate.kt
  20. 27 0
      App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/isDateValid.kt

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

@@ -4,6 +4,14 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
+        <DropdownSelection timestamp="2024-11-15T18:36:17.788996900Z">
+          <Target type="DEFAULT_BOOT">
+            <handle>
+              <DeviceId pluginId="PhysicalDevice" identifier="serial=VKUK5TAU7D55R4ZH" />
+            </handle>
+          </Target>
+        </DropdownSelection>
+        <DialogSelection />
       </SelectionState>
     </selectionStates>
   </component>

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

@@ -9,6 +9,7 @@ import androidx.activity.viewModels
 import androidx.annotation.RequiresApi
 import com.example.mystictale.ViewModels.AuthViewModel
 import com.example.mystictale.navigation.Navigation
+import com.example.mystictale.resources.components.dateComponents.isDateValid
 import com.example.mystictale.ui.theme.MysticTaleTheme
 
 class MainActivity : ComponentActivity() {
@@ -22,6 +23,7 @@ class MainActivity : ComponentActivity() {
 
                 Navigation()
 
+
             }
         }
     }

+ 2 - 0
App/app/src/main/java/com/example/mystictale/Screen/Start.kt

@@ -28,6 +28,7 @@ import androidx.compose.ui.unit.sp
 import androidx.navigation.NavController
 import com.example.mystictale.R
 import com.example.mystictale.navigation.Screens
+import com.example.mystictale.resources.components.Loading
 import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.OpenSans
 import com.example.mystictale.ui.theme.Wolgadeutsche
@@ -43,6 +44,7 @@ fun Start(navController: NavController) {
             ),
         contentAlignment = Alignment.Center
     ) {
+
         Column(
             Modifier
                 .fillMaxHeight(0.5f)

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

@@ -110,14 +110,15 @@ fun NewPassword(navController: NavController) {
                 PasswordTextField(
                     value = password.value,
                     onValueChange = { password.value = it },
-                    placeholder = "Пароль"
+                    placeholder = "Пароль",
+                    false
                 )
                 Spacer(modifier = Modifier.height(30.dp))
 
                 PasswordTextField(
                     value = repeatedPassword.value,
                     onValueChange = { repeatedPassword.value = it },
-                    placeholder = "Повторный пароль"
+                    placeholder = "Повторный пароль",false
                 )
             }
         }

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

@@ -119,7 +119,13 @@ fun PasswordRecovery(navController: NavController) {
                 Spacer(modifier = Modifier.height(30.dp))
 
 
-                GenericTextField(email.value, { email.value = it }, "E-mail", KeyboardType.Email)
+                GenericTextField(
+                    email.value,
+                    { email.value = it },
+                    "E-mail",
+                    KeyboardType.Email,
+                    false
+                )
 
             }
 

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

@@ -44,6 +44,8 @@ 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.ValidationDate
+import com.example.mystictale.resources.components.dateComponents.isDateValid
 import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.Grey
 import com.example.mystictale.ui.theme.OpenSans
@@ -69,6 +71,8 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
     val dateOfBirth = remember {
         mutableStateOf("")
     }
+    val dateFlag = remember { mutableStateOf(false) }
+    val formatter = DateTimeFormatter.ofPattern("ddMMyyyy")
     Column(
         Modifier
             .fillMaxSize()
@@ -130,7 +134,11 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
                 Spacer(modifier = Modifier.height(30.dp))
                 Text(
                     text = "Ваша дата рождения",
@@ -139,29 +147,73 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
                     fontSize = 24.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(start = 35.dp),
+                        .fillMaxWidth(),
                     style = MaterialTheme.typography.headlineMedium
                 )
                 Spacer(modifier = Modifier.height(30.dp))
 
                 DateOfBirthTextField(
                     dateOfBirth = dateOfBirth.value,
-                    onValue = { dob -> dateOfBirth.value = dob.filter { it.isDigit() } },
-                    dateDialogState = dateDialogState
+                    onValue = { dob ->if(dob.length<=8){
+                        dateOfBirth.value = dob.filter { it.isDigit() }
+                        dateFlag.value = false
+                    }
+                    },
+                    dateDialogState = dateDialogState,
+                    flag = dateFlag.value
                 )
+                if (dateFlag.value) {
+                    if (dateOfBirth.value.isEmpty()) {
+                        Text(
+                            "Введите дату рождения",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (dateOfBirth.value.length < 8) {
+                        Text(
+                            "Неверная дата рождения",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (!isDateValid(dateOfBirth.value)) {
+                        Text(
+                            "Неверная дата рождения",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    } else if (LocalDate.parse(dateOfBirth.value, formatter) > LocalDate.now()) {
+                        Text(
+                            "Неверная дата рождения",
+                            fontWeight = FontWeight.Light,
+                            fontFamily = OpenSans,
+                            fontSize = 13.sp,
+                            color = Color.Red
+                        )
+                    }
+                }
             }
         }
 
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.dateOfBirth = formattedDateFromBase
-                    navController.navigate(Screens.RegistrationGender.route)
+                    if (ValidationDate(dateOfBirth.value, formatter)) {
+                        dateFlag.value = true
+                    } else {
+                        viewModel.dateOfBirth = formattedDateFromBase
+                        navController.navigate(Screens.RegistrationGender.route)
+                    }
                 },
                 modifier = Modifier
-                    .width(290.dp)
-                    .height(48.dp),
+                    .fillMaxWidth()
+                    .height(48.dp)
+                    .padding(horizontal = 30.dp),
                 shape = RoundedCornerShape(12.dp),
                 colors = ButtonColors(
                     containerColor = DarkPurple,
@@ -202,3 +254,5 @@ fun RegistrationDateOfBirth(navController: NavController, viewModel: AuthViewMod
 }
 
 
+
+

+ 38 - 9
App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationEmail.kt

@@ -1,5 +1,6 @@
 package com.example.mystictale.Screen.registration
 
+import android.util.Patterns
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Arrangement
@@ -51,6 +52,7 @@ fun RegistrationEmail(navController: NavController, viewModel: AuthViewModel) {
     val email = remember {
         mutableStateOf("")
     }
+    val emailFlag = remember { mutableStateOf(false) }
     Column(
         Modifier
             .fillMaxSize()
@@ -112,33 +114,60 @@ fun RegistrationEmail(navController: NavController, viewModel: AuthViewModel) {
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
                 Spacer(modifier = Modifier.height(30.dp))
                 Text(
-                    text = "Ваша электронная почта",
+                    text = "Ваша электронная\n" +
+                            "почта",
                     fontWeight = FontWeight.Bold,
                     fontFamily = OpenSans,
                     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))
 
-                GenericTextField(email.value, { email.value = it }, "E-mail", KeyboardType.Email)
+                GenericTextField(
+                    email.value,
+                    {
+                        email.value = it
+                        emailFlag.value = false
+                    },
+                    "E-mail",
+                    KeyboardType.Email,
+                    flag = emailFlag.value
+                )
+                if (emailFlag.value) {
+                    Text(
+                        "Неверно введена почта",
+                        fontWeight = FontWeight.Light,
+                        fontFamily = OpenSans,
+                        fontSize = 13.sp,
+                        color = Color.Red
+                    )
+                }
             }
         }
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.email = email.value
-                    navController.navigate(Screens.RegistrationPassword.route)
+                    if (Patterns.EMAIL_ADDRESS.matcher(email.value).matches()) {
+                        viewModel.emailUser = email.value
+                        navController.navigate(Screens.RegistrationPassword.route)
+                    } else {
+                        emailFlag.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,

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

@@ -26,7 +26,6 @@ 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.BlendMode.Companion.Screen
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.StrokeCap
 import androidx.compose.ui.layout.ContentScale
@@ -41,6 +40,7 @@ import com.example.mystictale.ViewModels.AuthViewModel
 import com.example.mystictale.models.UserState
 import com.example.mystictale.navigation.Screens
 import com.example.mystictale.resources.components.ChooseGender
+import com.example.mystictale.resources.components.Loading
 import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.OpenSans
 
@@ -48,6 +48,8 @@ import com.example.mystictale.ui.theme.OpenSans
 fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
     val userState by viewModel.userState
     val flag = remember { mutableStateOf(false) }
+    val genderFlag = remember { mutableStateOf(false) }
+
     val context = LocalContext.current
     Column(
         Modifier
@@ -104,7 +106,11 @@ fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
                 Spacer(modifier = Modifier.height(30.dp))
                 Text(
                     text = "Ваш пол",
@@ -113,20 +119,38 @@ fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
                     fontSize = 24.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(horizontal = 35.dp),
+                        .fillMaxWidth(),
                     style = MaterialTheme.typography.headlineMedium
                 )
                 Spacer(modifier = Modifier.height(30.dp))
                 ChooseGender(viewModel)
+                if(genderFlag.value){
+                    Text(
+                        "Выберете пол",
+                        fontWeight = FontWeight.Light,
+                        fontFamily = OpenSans,
+                        fontSize = 13.sp,
+                        color = Color.Red
+                    )
+                }
+
             }
         }
         Box(Modifier.padding(bottom = 40.dp)) {
             Button(
-                onClick = {viewModel.onSignUpEmailPassword(context = context) },
+                onClick = {
+                    if(viewModel.gender==null){
+                        genderFlag.value = true
+                    }
+                    else{
+                        viewModel.onSignUpEmailPassword(context = context)
+                        flag.value = true
+                    }
+                },
                 modifier = Modifier
-                    .width(290.dp)
-                    .height(48.dp),
+                    .fillMaxWidth()
+                    .height(48.dp)
+                    .padding(horizontal = 30.dp),
                 shape = RoundedCornerShape(12.dp),
                 colors = ButtonColors(
                     containerColor = DarkPurple,
@@ -143,14 +167,13 @@ fun RegistrationGender(navController: NavController, viewModel: AuthViewModel) {
 
 
     }
-    if(flag.value){
+    if (flag.value) {
         when (userState) {
             is UserState.Loading -> {
-               CircularProgressIndicator()
+                Loading()
             }
 
             is UserState.Success -> {
-                val message = (userState as UserState.Success).message
                 navController.navigate(Screens.Start.route)
                 flag.value = false
             }

+ 31 - 8
App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationName.kt

@@ -51,6 +51,9 @@ fun RegistrationName(navController: NavController, viewModel: AuthViewModel) {
     val name = remember {
         mutableStateOf("")
     }
+    val nameFlag = remember {
+        mutableStateOf(false)
+    }
     Column(
         Modifier
             .fillMaxSize()
@@ -112,7 +115,11 @@ fun RegistrationName(navController: NavController, viewModel: AuthViewModel) {
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
                 Spacer(modifier = Modifier.height(30.dp))
 
                 Text(
@@ -122,13 +129,24 @@ fun RegistrationName(navController: NavController, viewModel: AuthViewModel) {
                     fontSize = 24.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(start = 35.dp),
+                        .fillMaxWidth(),
                     style = MaterialTheme.typography.headlineMedium
                 )
                 Spacer(modifier = Modifier.height(30.dp))
 
-                GenericTextField(name.value, { name.value = it }, "Имя", KeyboardType.Text)
+                GenericTextField(name.value, {
+                    name.value = it
+                    nameFlag.value = false
+                }, "Имя", KeyboardType.Text, nameFlag.value)
+                if (nameFlag.value) {
+                    Text(
+                        "Введите имя",
+                        fontWeight = FontWeight.Light,
+                        fontFamily = OpenSans,
+                        fontSize = 13.sp,
+                        color = Color.Red
+                    )
+                }
             }
         }
 
@@ -137,12 +155,17 @@ fun RegistrationName(navController: NavController, viewModel: AuthViewModel) {
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.name = name.value
-                    navController.navigate(Screens.RegistrationDateOfBirth.route)
+                    if (name.value.isEmpty()) {
+                        nameFlag.value = true
+                    } else {
+                        viewModel.name = name.value
+                        navController.navigate(Screens.RegistrationDateOfBirth.route)
+                    }
                 },
                 modifier = Modifier
-                    .width(310.dp)
-                    .height(48.dp),
+                    .fillMaxWidth()
+                    .height(48.dp)
+                    .padding(horizontal = 30.dp),
                 shape = RoundedCornerShape(12.dp),
                 colors = ButtonColors(
                     containerColor = DarkPurple,

+ 71 - 11
App/app/src/main/java/com/example/mystictale/Screen/registration/RegistrationPassword.kt

@@ -34,11 +34,13 @@ 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
 import com.example.mystictale.navigation.Screens
 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.Grey
 import com.example.mystictale.ui.theme.OpenSans
@@ -53,6 +55,7 @@ fun RegistrationPassword(navController: NavController, viewModel: AuthViewModel)
     val repeatedPassword = remember {
         mutableStateOf("")
     }
+    val passwordFlag = remember { mutableStateOf(false) }
     Column(
         Modifier
             .fillMaxSize()
@@ -114,7 +117,11 @@ fun RegistrationPassword(navController: NavController, viewModel: AuthViewModel)
                     )
                 }
             }
-            Column(modifier = Modifier.padding(10.dp)) {
+            Column(
+                modifier = Modifier
+                    .padding(20.dp)
+                    .padding(start = 15.dp, end = 5.dp)
+            ) {
                 Spacer(modifier = Modifier.height(30.dp))
                 Text(
                     text = "Придумайте пароль",
@@ -123,8 +130,7 @@ fun RegistrationPassword(navController: NavController, viewModel: AuthViewModel)
                     fontSize = 24.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(start = 35.dp),
+                        .fillMaxWidth(),
                     style = MaterialTheme.typography.headlineMedium
                 )
                 Spacer(modifier = Modifier.height(30.dp))
@@ -138,22 +144,71 @@ fun RegistrationPassword(navController: NavController, viewModel: AuthViewModel)
                     fontSize = 13.sp,
                     color = Color.White,
                     modifier = Modifier
-                        .fillMaxWidth(0.9f)
-                        .padding(start = 40.dp)
+                        .fillMaxWidth()
                 )
 
 
                 Spacer(modifier = Modifier.height(30.dp))
 
-                PasswordTextField(password.value, { password.value = it }, "Пароль")
+                PasswordTextField(
+                    password.value, {
+                        password.value = it
+                        passwordFlag.value = false
+                    }, "Пароль",
+                    passwordFlag.value
+                )
 
                 Spacer(modifier = Modifier.height(30.dp))
 
                 PasswordTextField(
                     repeatedPassword.value,
                     { repeatedPassword.value = it },
-                    "Повторный пароль"
+                    "Повторный пароль",
+                    passwordFlag.value
                 )
+                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
+                        )
+                    }
+                }
             }
         }
 
@@ -161,12 +216,17 @@ fun RegistrationPassword(navController: NavController, viewModel: AuthViewModel)
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
                 onClick = {
-                    viewModel.password = password.value
-                    navController.navigate(Screens.RegistrationName.route)
+                    if (!ValidationPassword(password.value, repeatedPassword.value)) {
+                        viewModel.passwordUser = password.value
+                        navController.navigate(Screens.RegistrationName.route)
+                    } 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,

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

@@ -111,9 +111,15 @@ fun SignIn(navController: NavController) {
                 )
                 Spacer(modifier = Modifier.height(30.dp))
 
-                GenericTextField(email.value, { email.value = it }, "E-mail", KeyboardType.Email)
+                GenericTextField(
+                    email.value,
+                    { email.value = it },
+                    "E-mail",
+                    KeyboardType.Email,
+                    false
+                )
                 Spacer(modifier = Modifier.height(30.dp))
-                PasswordTextField(password.value, { password.value = it }, "Пароль")
+                PasswordTextField(password.value, { password.value = it }, "Пароль",false)
                 Spacer(modifier = Modifier.height(30.dp))
                 Text(
                     "Забыли пароль?",
@@ -130,7 +136,7 @@ fun SignIn(navController: NavController) {
 
         Box(Modifier.padding(bottom = 50.dp)) {
             Button(
-                onClick = {  },
+                onClick = { },
                 modifier = Modifier
                     .width(310.dp)
                     .height(48.dp),

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

@@ -18,8 +18,8 @@ import kotlinx.coroutines.launch
 class AuthViewModel: ViewModel() {
     private val _userState = mutableStateOf<UserState>(UserState.Loading)
     val userState: State<UserState> = _userState
-    var email by mutableStateOf<String?>(null)
-    var password 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)
@@ -28,8 +28,8 @@ class AuthViewModel: ViewModel() {
             try {
                 _userState.value = UserState.Loading
                 SupabaseConnect.supabase.auth.signUpWith(Email) {
-                    email
-                    password
+                    email = emailUser!!
+                    password = passwordUser!!
                 }
                 saveToken(context)
                 _userState.value = UserState.Success("Success sing up")

+ 24 - 41
App/app/src/main/java/com/example/mystictale/resources/components/ChooseGender.kt

@@ -1,6 +1,5 @@
 package com.example.mystictale.resources.components
 
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
@@ -26,7 +25,6 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.DpOffset
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.unit.toSize
@@ -35,17 +33,12 @@ import com.example.mystictale.ui.theme.DarkPurple
 import com.example.mystictale.ui.theme.OpenSans
 
 @Composable
-fun ChooseGender( viewModel: AuthViewModel) {
-    var expanded by remember {
-        mutableStateOf(false)
-    }
+fun ChooseGender(viewModel: AuthViewModel) {
+    var expanded by remember { mutableStateOf(false) }
     val list = listOf("Мужской", "Женский")
-    var selectedItem by remember {
-        mutableStateOf("")
-    }
-    var textFiledSize by remember {
-        mutableStateOf(Size.Zero)
-    }
+    var selectedItem by remember { mutableStateOf("") }
+    var buttonSize by remember { mutableStateOf(Size.Zero) }
+
     Column(
         modifier = Modifier
             .fillMaxWidth(),
@@ -55,10 +48,10 @@ fun ChooseGender( viewModel: AuthViewModel) {
         Button(
             onClick = { expanded = !expanded },
             modifier = Modifier
-                .width(290.dp)
+                .fillMaxWidth()
                 .height(56.dp)
                 .onGloballyPositioned { coordinates ->
-                    textFiledSize = coordinates.size.toSize()
+                    buttonSize = coordinates.size.toSize()
                 },
             shape = RoundedCornerShape(12.dp),
             colors = ButtonDefaults.buttonColors(
@@ -67,11 +60,9 @@ fun ChooseGender( viewModel: AuthViewModel) {
             ),
             contentPadding = PaddingValues(start = 16.dp, end = 16.dp)
         ) {
-            Row(
-                verticalAlignment = Alignment.CenterVertically
-            ) {
+            Row(verticalAlignment = Alignment.CenterVertically) {
                 Text(
-                    text = selectedItem.ifEmpty { "Выберете пол" },
+                    text = selectedItem.ifEmpty { "Выберите пол" },
                     fontSize = 20.sp,
                     fontFamily = OpenSans,
                     fontWeight = FontWeight.Bold,
@@ -84,32 +75,24 @@ fun ChooseGender( viewModel: AuthViewModel) {
             expanded = expanded,
             onDismissRequest = { expanded = false },
             modifier = Modifier
-                .width(with(LocalDensity.current) { textFiledSize.width.toDp() })
-                .background(Color.White),
-            offset = DpOffset(
-                x = 43.dp,
-                y = 0.dp
-            )
-
+                .width(with(LocalDensity.current) { buttonSize.width.toDp() })
         ) {
             list.forEach { label ->
-                DropdownMenuItem(text = {
-                    Text(
-                        text = label,
-                        fontSize = 15.sp,
-                        fontWeight = FontWeight.Normal
-                    )
-                }, onClick = {
-                    selectedItem = label
-                    expanded = false
-                    if(selectedItem == "Женский"){
-                        viewModel.gender = 1
-                    }else{
-                        viewModel.gender = 2
+                DropdownMenuItem(
+                    text = {
+                        Text(
+                            text = label,
+                            fontSize = 15.sp,
+                            fontWeight = FontWeight.Normal
+                        )
+                    },
+                    onClick = {
+                        selectedItem = label
+                        expanded = false
+                        viewModel.gender = if (selectedItem == "Женский") 1 else 2
                     }
-
-                })
+                )
             }
         }
     }
-}
+}

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

@@ -1,7 +1,6 @@
 package com.example.mystictale.resources.components
 
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextField
@@ -12,18 +11,22 @@ 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.KeyboardType
-import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import com.example.mystictale.ui.theme.OpenSans
 
 @Composable
-fun GenericTextField(value:String, onValue:(String) -> Unit,placeholder:String, keyboardType:KeyboardType) {
+fun GenericTextField(
+    value: String,
+    onValue: (String) -> Unit,
+    placeholder: String,
+    keyboardType: KeyboardType,
+    flag: Boolean
+) {
     TextField(
         value = value,
         onValueChange = onValue,
         Modifier
-            .padding(start = 30.dp)
-            .width(310.dp),
+            .fillMaxWidth(),
         keyboardOptions = KeyboardOptions(
             keyboardType = keyboardType
         ),
@@ -35,8 +38,12 @@ fun GenericTextField(value:String, onValue:(String) -> Unit,placeholder:String,
             focusedContainerColor = Color.Transparent,
             focusedPlaceholderColor = Color(0xffA1A0A3),
             focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B)
+            unfocusedIndicatorColor = Color(0xff28176B),
+            errorContainerColor = Color.Transparent,
+            errorTextColor = Color.White,
+            errorPlaceholderColor = Color(0xffA1A0A3),
         ),
+        isError = flag,
         placeholder = { Text(text = placeholder) },
         maxLines = 1,
         textStyle = TextStyle(

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

@@ -0,0 +1,22 @@
+package com.example.mystictale.resources.components
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+
+@Composable
+fun Loading() {
+    Column(
+        Modifier.fillMaxSize().background(Color(0x40FFFFFF)),
+        verticalArrangement = Arrangement.Center,
+        horizontalAlignment = Alignment.CenterHorizontally
+    ) {
+        CircularProgressIndicator()
+    }
+}

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

@@ -1,6 +1,6 @@
 package com.example.mystictale.resources.components
 
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.Icon
@@ -25,14 +25,18 @@ import com.example.mystictale.R
 import com.example.mystictale.ui.theme.OpenSans
 
 @Composable
-fun PasswordTextField(value:String, onValueChange:(String)->Unit,placeholder: String) {
+fun PasswordTextField(
+    value: String,
+    onValueChange: (String) -> Unit,
+    placeholder: String,
+    flag: Boolean
+) {
     val checked = remember { mutableStateOf(false) }
     TextField(
         value = value,
         onValueChange = onValueChange,
         Modifier
-            .padding(start = 30.dp)
-            .width(310.dp),
+            .fillMaxWidth(),
         trailingIcon = {
             IconToggleButton(
                 checked = checked.value,
@@ -49,6 +53,7 @@ fun PasswordTextField(value:String, onValueChange:(String)->Unit,placeholder: St
                 )
             }
         },
+        isError = flag,
         keyboardOptions = KeyboardOptions(
             keyboardType = KeyboardType.Password
         ),
@@ -61,7 +66,10 @@ fun PasswordTextField(value:String, onValueChange:(String)->Unit,placeholder: St
             focusedContainerColor = Color.Transparent,
             focusedPlaceholderColor = Color(0xffA1A0A3),
             focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B)
+            unfocusedIndicatorColor = Color(0xff28176B),
+            errorContainerColor = Color.Transparent,
+            errorTextColor = Color.White,
+            errorPlaceholderColor = Color(0xffA1A0A3),
         ),
         placeholder = { Text(text = placeholder) },
         maxLines = 1,

+ 13 - 1
App/app/src/main/java/com/example/mystictale/resources/components/ValidationPassword.kt

@@ -1,5 +1,17 @@
 package com.example.mystictale.resources.components
 
 
-class ValidationPasswoed {
+fun ValidationPassword(password: String, repeatedPassword: String): Boolean {
+    if (password.isEmpty()) {
+        return true
+    } else if (password.length < 6) {
+        return true
+    } else if (!password.any { it.isLetter() }) {
+        return true
+    } else if (!password.any { it.isDigit() }) {
+        return true
+    } else if (password != repeatedPassword) {
+        return true
+    }
+    return false
 }

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

@@ -1,9 +1,9 @@
 package com.example.mystictale.resources.components.dateComponents
 
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.DateRange
@@ -23,17 +23,22 @@ import com.example.mystictale.ui.theme.OpenSans
 import com.vanpra.composematerialdialogs.MaterialDialogState
 
 @Composable
-fun DateOfBirthTextField(dateOfBirth:String,onValue:(String) -> Unit,dateDialogState: MaterialDialogState) {
+fun DateOfBirthTextField(
+    dateOfBirth: String,
+    onValue: (String) -> Unit,
+    dateDialogState: MaterialDialogState,
+    flag: Boolean
+) {
     val padding = 10.dp;
     TextField(
         value = dateOfBirth,
         onValueChange = onValue,
         Modifier
-            .padding(start = 30.dp)
-            .width(310.dp),
+            .fillMaxWidth(),
         keyboardOptions = KeyboardOptions(
             keyboardType = KeyboardType.Number
         ),
+
         colors = TextFieldDefaults.colors(
             unfocusedTextColor = Color.White,
             unfocusedPlaceholderColor = Color(0xffA1A0A3),
@@ -42,8 +47,12 @@ fun DateOfBirthTextField(dateOfBirth:String,onValue:(String) -> Unit,dateDialogS
             focusedContainerColor = Color.Transparent,
             focusedPlaceholderColor = Color(0xffA1A0A3),
             focusedIndicatorColor = Color(0xff28176B),
-            unfocusedIndicatorColor = Color(0xff28176B)
+            unfocusedIndicatorColor = Color(0xff28176B),
+            errorContainerColor = Color.Transparent,
+            errorTextColor = Color.White,
+            errorPlaceholderColor = Color(0xffA1A0A3),
         ),
+        isError = flag,
         trailingIcon = {
             Icon(
                 Icons.Filled.DateRange,

+ 21 - 1
App/app/src/main/java/com/example/mystictale/resources/components/dateComponents/ValidationDate.kt

@@ -1,5 +1,25 @@
 package com.example.mystictale.resources.components.dateComponents
 
+import android.os.Build
+import androidx.annotation.RequiresApi
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
 
-class ValidationDate {
+
+@RequiresApi(Build.VERSION_CODES.O)
+fun ValidationDate(
+    dateOfBirth: String,
+    formatter: DateTimeFormatter
+): Boolean {
+
+    if (dateOfBirth.isEmpty()) {
+        return true
+    } else if (dateOfBirth.length < 8) {
+        return true
+    } else if (!isDateValid(dateOfBirth)) {
+        return true
+    } else if (LocalDate.parse(dateOfBirth, formatter) > LocalDate.now()) {
+        return true
+    }
+    return false
 }

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

@@ -1,3 +1,30 @@
 package com.example.mystictale.resources.components.dateComponents
 
+import android.os.Build
+import androidx.annotation.RequiresApi
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeParseException
+import java.time.format.ResolverStyle
+import java.util.Locale
 
+
+@RequiresApi(Build.VERSION_CODES.O)
+fun isDateValid(dateString: String): Boolean {
+    if (dateString.length != 8) return false
+
+    // Определяем формат даты ddMMyyyy
+    val formatter = DateTimeFormatter.ofPattern("ddMMyyyy")
+
+    return try {
+        // Пробуем преобразовать строку в дату
+        val parsedDate = LocalDate.parse(dateString, formatter)
+        println(parsedDate)
+
+        // Если успешно, возвращаем true
+        true
+    } catch (e: DateTimeParseException) {
+        // Если возникает исключение, возвращаем false
+        false
+    }
+}