diff --git a/composeApp/src/commonMain/composeResources/values-sk/strings.xml b/composeApp/src/commonMain/composeResources/values-sk/strings.xml index f139777..4ca07ed 100644 --- a/composeApp/src/commonMain/composeResources/values-sk/strings.xml +++ b/composeApp/src/commonMain/composeResources/values-sk/strings.xml @@ -60,6 +60,7 @@ Všetko je pripravené! Začať je ľahké – vyberte si, čo a kde by ste chceli zbierať. Tešíme sa na naše spoločné dobrodružstvá pri zbieraní! Začnite používať aplikáciu! + Zadajte meno Detaily zberu Hlavný obrázok udalosti Prihlásiť sa na zber @@ -111,11 +112,13 @@ Názov je požadovaný Kapacita je požadovaná + Kapacita nie je validná Dátum je požadovaný Čas je požadovaný Dátum a čas musia byť v budúcnosti Miesto je požadované Suma platu je požadovaná + Suma platu nie je validná Vytvoriť zber Aktualizovať zber diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 2eb9dab..cf0acc6 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -75,6 +75,7 @@ Everything is prepared! Getting started is easy – choose what and where you'd like to harvest. We're excited for our shared gathering adventures! Start using application! + Name cannot be empty! Harvest Detail Event featured image @@ -130,11 +131,13 @@ Title is required Capacity is required + Capacity is invalid Date is required Time is required Date and time must be in future Location is required Salary amount is required + Salary amount is invalid Create harvest Update harvest diff --git a/composeApp/src/commonMain/kotlin/auth/domain/AuthError.kt b/composeApp/src/commonMain/kotlin/auth/domain/AuthError.kt index b84bc7f..bd111d0 100644 --- a/composeApp/src/commonMain/kotlin/auth/domain/AuthError.kt +++ b/composeApp/src/commonMain/kotlin/auth/domain/AuthError.kt @@ -14,4 +14,8 @@ sealed interface AuthError : Error { enum class TokenError : AuthError { EXPIRED } + + enum class ProfileError : AuthError { + EMPTY_NAME + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/auth/domain/AuthValidation.kt b/composeApp/src/commonMain/kotlin/auth/domain/AuthValidation.kt index adc307f..2be2462 100644 --- a/composeApp/src/commonMain/kotlin/auth/domain/AuthValidation.kt +++ b/composeApp/src/commonMain/kotlin/auth/domain/AuthValidation.kt @@ -21,7 +21,8 @@ class AuthValidation { if (password.length < 8) { emit(ResultHandler.Error(AuthError.PasswordError.TOO_SHORT)) } else { - val hasDigit = password.all { it.isDigit() } + println(password) + val hasDigit = password.any { it.isDigit() } if (!hasDigit) { emit(ResultHandler.Error(AuthError.PasswordError.NO_DIGIT)) } else { @@ -36,8 +37,18 @@ class AuthValidation { ): Flow> = flow { if (password != passwordRepeated) { emit(ResultHandler.Error(AuthError.PasswordError.NO_MATCH)) + } else { + emit(ResultHandler.Success(true)) } + } - emit(ResultHandler.Success(true)) + suspend fun validateName( + name: String, + ): Flow> = flow { + if (name.isEmpty()) { + emit(ResultHandler.Error(AuthError.ProfileError.EMPTY_NAME)) + } else { + emit(ResultHandler.Success(true)) + } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/auth/presentation/login/component/LoginScreenComponent.kt b/composeApp/src/commonMain/kotlin/auth/presentation/login/component/LoginScreenComponent.kt index 8279981..6295f00 100644 --- a/composeApp/src/commonMain/kotlin/auth/presentation/login/component/LoginScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/auth/presentation/login/component/LoginScreenComponent.kt @@ -42,16 +42,15 @@ class LoginScreenComponent( } is LoginScreenEvent.ClickLoginButton -> { - println(_stateLogin.value) -// validateEmail() -// validatePassword() - - loginUser( - login = Login( - email = _stateLogin.value.email, - password = _stateLogin.value.password + validateForm() + if (isFormValid()) { + loginUser( + login = Login( + email = _stateLogin.value.email, + password = _stateLogin.value.password + ) ) - ) + } } is LoginScreenEvent.UpdateEmail -> { @@ -71,24 +70,27 @@ class LoginScreenComponent( } private fun isFormValid(): Boolean { - return _stateLogin.value.email.isNotEmpty() && _stateLogin.value.password.isNotEmpty() && _stateLogin.value.emailError != null && _stateLogin.value.passwordError != null + return _stateLogin.value.email.isNotEmpty() && _stateLogin.value.password.isNotEmpty() && _stateLogin.value.emailError == null && _stateLogin.value.passwordError == null + } + + private fun validateForm() { + validateEmail() + if (_stateLogin.value.emailError == null) { + validatePassword() + } } private fun validateEmail() { coroutineScope().launch { authValidation.validateEmail(_stateLogin.value.email).collect { result -> if (result is ResultHandler.Error) { - println("Email result: $result") _stateLogin.value = _stateLogin.value.copy( emailError = result.error.asUiText().asNonCompString() ) - println(result) - println(_stateLogin.value) } else if (result is ResultHandler.Success) { _stateLogin.value = _stateLogin.value.copy( emailError = null ) - println(_stateLogin.value) } } } @@ -98,21 +100,16 @@ class LoginScreenComponent( coroutineScope().launch { authValidation.validatePassword(_stateLogin.value.password).collect { result -> if (result is ResultHandler.Error) { - println("Password result: $result") _stateLogin.value = _stateLogin.value.copy( passwordError = result.error.asUiText().asNonCompString() ) - println(result) - println(_stateLogin.value) } else if (result is ResultHandler.Success) { _stateLogin.value = _stateLogin.value.copy( passwordError = null ) - println(_stateLogin.value) } } } - println(_stateLogin.value) } private fun loginUser(login: Login) { diff --git a/composeApp/src/commonMain/kotlin/auth/presentation/register/RegisterStep1Screen.kt b/composeApp/src/commonMain/kotlin/auth/presentation/register/RegisterStep1Screen.kt index 1f03f6f..a498486 100644 --- a/composeApp/src/commonMain/kotlin/auth/presentation/register/RegisterStep1Screen.kt +++ b/composeApp/src/commonMain/kotlin/auth/presentation/register/RegisterStep1Screen.kt @@ -6,16 +6,26 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.SnackbarDuration +import androidx.compose.material.SnackbarHost +import androidx.compose.material.SnackbarHostState +import androidx.compose.material.SnackbarResult import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager @@ -31,6 +41,8 @@ import com.arkivanov.decompose.extensions.compose.subscribeAsState import core.presentation.components.button_primary.ButtonPrimary import core.presentation.components.filled_input.FilledInput import core.presentation.components.logo.GrabItLogo +import core.presentation.components.snackbar.CustomSnackbar +import core.presentation.components.snackbar.SnackbarVisualWithError import grabit.composeapp.generated.resources.Res import grabit.composeapp.generated.resources.create_account import grabit.composeapp.generated.resources.email @@ -39,6 +51,7 @@ import grabit.composeapp.generated.resources.next_step import grabit.composeapp.generated.resources.password import grabit.composeapp.generated.resources.register_screen__has_account import grabit.composeapp.generated.resources.repeat_password +import kotlinx.coroutines.launch import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.stringResource import ui.domain.ColorVariation @@ -49,90 +62,131 @@ import ui.theme.LightOnOrange fun RegisterStep1Screen(component: RegisterStep1ScreenComponent) { val stateRegisterStep1 by component.stateRegisterStep1.subscribeAsState() + val coroutineScope = rememberCoroutineScope() + val snackbarHostState = remember { SnackbarHostState() } + val isVisible = remember { mutableStateOf(false) } + val focusManager = LocalFocusManager.current - Column( - modifier = Modifier.fillMaxHeight().background(MaterialTheme.colors.background) - .padding(40.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer(modifier = Modifier.height(80.dp)) - GrabItLogo() - Spacer(modifier = Modifier.height(48.dp)) - Text( - stringResource(Res.string.create_account), - style = MaterialTheme.typography.h2, - color = MaterialTheme.colors.onBackground - ) - Spacer(modifier = Modifier.height(24.dp)) + if (!isVisible.value && stateRegisterStep1.error != null) { + coroutineScope.launch { + isVisible.value = true + val snackbarResult = snackbarHostState.showSnackbar( + message = stateRegisterStep1.error!!, + duration = SnackbarDuration.Short + ) + + when (snackbarResult) { + SnackbarResult.Dismissed -> { + isVisible.value = false + component.onEvent(RegisterStep1ScreenEvent.RemoveError) + } + + SnackbarResult.ActionPerformed -> { + isVisible.value = false + component.onEvent(RegisterStep1ScreenEvent.RemoveError) + } + } + } + } + Scaffold( + modifier = Modifier.fillMaxSize().navigationBarsPadding(), + snackbarHost = { + SnackbarHost(hostState = snackbarHostState, snackbar = { + CustomSnackbar( + data = SnackbarVisualWithError( + snackbarData = it, + isError = true, + ) + ) + }) + }, + ) { Column( - verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.fillMaxHeight().background(MaterialTheme.colors.background) + .padding(40.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - FilledInput( - value = stateRegisterStep1.email, - onValueChange = { component.onEvent(RegisterStep1ScreenEvent.UpdateEmail(it)) }, - label = stringResource(Res.string.email), - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Email, - imeAction = ImeAction.Next - ) + Spacer(modifier = Modifier.height(80.dp)) + GrabItLogo() + Spacer(modifier = Modifier.height(48.dp)) + Text( + stringResource(Res.string.create_account), + style = MaterialTheme.typography.h2, + color = MaterialTheme.colors.onBackground ) - FilledInput( - value = stateRegisterStep1.password, - onValueChange = { component.onEvent(RegisterStep1ScreenEvent.UpdatePassword(it)) }, - label = stringResource(Res.string.password), - visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Password, - imeAction = ImeAction.Next + Spacer(modifier = Modifier.height(24.dp)) + + Column( + verticalArrangement = Arrangement.spacedBy(12.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + FilledInput( + value = stateRegisterStep1.email, + onValueChange = { component.onEvent(RegisterStep1ScreenEvent.UpdateEmail(it)) }, + label = stringResource(Res.string.email), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Email, + imeAction = ImeAction.Next + ) ) - ) - FilledInput( - value = stateRegisterStep1.passwordRepeated, - onValueChange = { - component.onEvent( - RegisterStep1ScreenEvent.UpdatePasswordRepeated( - it - ) + FilledInput( + value = stateRegisterStep1.password, + onValueChange = { component.onEvent(RegisterStep1ScreenEvent.UpdatePassword(it)) }, + label = stringResource(Res.string.password), + visualTransformation = PasswordVisualTransformation(), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + imeAction = ImeAction.Next ) - }, - label = stringResource(Res.string.repeat_password), - visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Done - ), - keyboardActions = KeyboardActions { - focusManager.clearFocus() - } - ) - ButtonPrimary( - type = ColorVariation.ORANGE, - onClick = { - component.onEvent(RegisterStep1ScreenEvent.ClickButtonNext) - }, - text = stringResource(Res.string.next_step) - ) - Row(verticalAlignment = Alignment.CenterVertically) { - Text( - stringResource( - Res.string.register_screen__has_account - ), - style = MaterialTheme.typography.body2, - color = MaterialTheme.colors.onBackground ) - Spacer(Modifier.width(4.dp)) - ClickableText( - text = AnnotatedString(stringResource(Res.string.login_screen__login)), - onClick = { component.onEvent(RegisterStep1ScreenEvent.GoBackToLogin) }, - style = TextStyle( - color = LightOnOrange, - fontSize = MaterialTheme.typography.body2.fontSize, - fontWeight = MaterialTheme.typography.body2.fontWeight + FilledInput( + value = stateRegisterStep1.passwordRepeated, + onValueChange = { + component.onEvent( + RegisterStep1ScreenEvent.UpdatePasswordRepeated( + it + ) + ) + }, + label = stringResource(Res.string.repeat_password), + visualTransformation = PasswordVisualTransformation(), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Done ), + keyboardActions = KeyboardActions { + focusManager.clearFocus() + } + ) + ButtonPrimary( + type = ColorVariation.ORANGE, + onClick = { + focusManager.clearFocus() + component.onEvent(RegisterStep1ScreenEvent.ClickButtonNext) + }, + text = stringResource(Res.string.next_step) ) + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + stringResource( + Res.string.register_screen__has_account + ), + style = MaterialTheme.typography.body2, + color = MaterialTheme.colors.onBackground + ) + Spacer(Modifier.width(4.dp)) + ClickableText( + text = AnnotatedString(stringResource(Res.string.login_screen__login)), + onClick = { component.onEvent(RegisterStep1ScreenEvent.GoBackToLogin) }, + style = TextStyle( + color = LightOnOrange, + fontSize = MaterialTheme.typography.body2.fontSize, + fontWeight = MaterialTheme.typography.body2.fontWeight + ), + ) + } } } } diff --git a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenComponent.kt b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenComponent.kt index 6262af7..1ef820b 100644 --- a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenComponent.kt @@ -8,6 +8,8 @@ import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.lifecycle.coroutines.coroutineScope +import core.domain.ResultHandler +import core.presentation.error_string_mapper.asUiText import kotlinx.coroutines.launch class RegisterStep1ScreenComponent( @@ -22,29 +24,28 @@ class RegisterStep1ScreenComponent( email = email, password = "", passwordRepeated = "", - error = null + error = null, ) ) val stateRegisterStep1: Value = _stateRegisterStep1 - private val _passwordsMatch = MutableValue(false) - val passwordsMatch: Value = _passwordsMatch - - private val _isValid = MutableValue(false) - val isValid: Value = _isValid - fun onEvent(event: RegisterStep1ScreenEvent) { when (event) { is RegisterStep1ScreenEvent.GoBackToLogin -> onNavigateBackToLoginScreen() - is RegisterStep1ScreenEvent.ClickButtonNext -> onNavigateToRegisterStep2Screen( - NewUser( - email = _stateRegisterStep1.value.email, - password = _stateRegisterStep1.value.password, - accountType = AccountType.HARVESTER, - name = "", - phoneNumber = null - ) - ) + is RegisterStep1ScreenEvent.ClickButtonNext -> { + validateForm() + if (isFormValid()) { + onNavigateToRegisterStep2Screen( + NewUser( + email = _stateRegisterStep1.value.email, + password = _stateRegisterStep1.value.password, + accountType = AccountType.HARVESTER, + name = "", + phoneNumber = null + ) + ) + } + } is RegisterStep1ScreenEvent.UpdateEmail -> { _stateRegisterStep1.value = _stateRegisterStep1.value.copy(email = event.email) @@ -61,10 +62,80 @@ class RegisterStep1ScreenComponent( passwordRepeated = event.passwordRepeated ) } + + RegisterStep1ScreenEvent.RemoveError -> { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = null + ) + } } } + private fun isFormValid(): Boolean { + return _stateRegisterStep1.value.email.isNotEmpty() + && _stateRegisterStep1.value.password.isNotEmpty() + && _stateRegisterStep1.value.passwordRepeated.isNotEmpty() + && _stateRegisterStep1.value.error == null + } + private fun validateForm() { -// authValidation.validateEmail(stateRegisterStep1.value.email) + validateEmail() + if (_stateRegisterStep1.value.error == null) { + validatePassword() + if (_stateRegisterStep1.value.error == null) { + validatePasswordMatch() + } + } + } + + private fun validateEmail() { + coroutineScope().launch { + authValidation.validateEmail(_stateRegisterStep1.value.email).collect { result -> + if (result is ResultHandler.Error) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = result.error.asUiText().asNonCompString() + ) + } else if (result is ResultHandler.Success) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = null + ) + } + } + } + } + + private fun validatePassword() { + coroutineScope().launch { + authValidation.validatePassword(_stateRegisterStep1.value.password).collect { result -> + if (result is ResultHandler.Error) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = result.error.asUiText().asNonCompString() + ) + } else if (result is ResultHandler.Success) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = null + ) + } + } + } + } + + private fun validatePasswordMatch() { + coroutineScope().launch { + authValidation.matchPasswords( + _stateRegisterStep1.value.password, + _stateRegisterStep1.value.passwordRepeated + ).collect { result -> + if (result is ResultHandler.Error) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = result.error.asUiText().asNonCompString() + ) + } else if (result is ResultHandler.Success) { + _stateRegisterStep1.value = _stateRegisterStep1.value.copy( + error = null + ) + } + } + } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenEvent.kt b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenEvent.kt index 83faeff..63b96c4 100644 --- a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenEvent.kt +++ b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep1ScreenEvent.kt @@ -6,4 +6,5 @@ sealed interface RegisterStep1ScreenEvent { data class UpdateEmail(val email: String) : RegisterStep1ScreenEvent data class UpdatePassword(val password: String) : RegisterStep1ScreenEvent data class UpdatePasswordRepeated(val passwordRepeated: String) : RegisterStep1ScreenEvent + data object RemoveError : RegisterStep1ScreenEvent } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep3ScreenComponent.kt b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep3ScreenComponent.kt index 99c4473..dc6e8e0 100644 --- a/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep3ScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/auth/presentation/register/component/RegisterStep3ScreenComponent.kt @@ -1,6 +1,7 @@ package auth.presentation.register.component import auth.data.remote.dto.toUser +import auth.domain.AuthValidation import auth.domain.model.NewUser import auth.domain.use_case.RegisterUserUseCase import auth.presentation.register.RegisterStep3State @@ -16,6 +17,7 @@ import kotlinx.coroutines.launch class RegisterStep3ScreenComponent( componentContext: ComponentContext, private val registerUserUseCase: RegisterUserUseCase, + private val authValidation: AuthValidation, newUser: NewUser, private val databaseClient: SqlDelightDatabaseClient, private val onNavigateToRegisterStepFinalScreen: () -> Unit @@ -47,15 +49,17 @@ class RegisterStep3ScreenComponent( } is RegisterStep3ScreenEvent.ClickCreateAccountButton -> { - createAccount( - newUser = _stateRegisterStep3State.value.newUser.copy( - name = _stateRegisterStep3State.value.name, - phoneNumber = _stateRegisterStep3State.value.phoneNumber + validateForm() + if (isFormValid()) + createAccount( + newUser = _stateRegisterStep3State.value.newUser.copy( + name = _stateRegisterStep3State.value.name, + phoneNumber = _stateRegisterStep3State.value.phoneNumber + ) ) - ) } - RegisterStep3ScreenEvent.RemoveError -> { + is RegisterStep3ScreenEvent.RemoveError -> { _stateRegisterStep3State.value = _stateRegisterStep3State.value.copy( error = null ) @@ -63,6 +67,30 @@ class RegisterStep3ScreenComponent( } } + private fun isFormValid(): Boolean { + return _stateRegisterStep3State.value.name.isNotEmpty() && _stateRegisterStep3State.value.error == null + } + + private fun validateForm() { + validateName() + } + + private fun validateName() { + coroutineScope().launch { + authValidation.validateName(_stateRegisterStep3State.value.name).collect { result -> + if (result is ResultHandler.Error) { + _stateRegisterStep3State.value = _stateRegisterStep3State.value.copy( + error = result.error.asUiText().asNonCompString() + ) + } else if (result is ResultHandler.Success) { + _stateRegisterStep3State.value = _stateRegisterStep3State.value.copy( + error = null + ) + } + } + } + } + private fun createAccount(newUser: NewUser) { this@RegisterStep3ScreenComponent.coroutineScope().launch { registerUserUseCase(newUser).collect { result -> diff --git a/composeApp/src/commonMain/kotlin/core/presentation/error_string_mapper/ErrorTextMapper.kt b/composeApp/src/commonMain/kotlin/core/presentation/error_string_mapper/ErrorTextMapper.kt index 7125552..0e63273 100644 --- a/composeApp/src/commonMain/kotlin/core/presentation/error_string_mapper/ErrorTextMapper.kt +++ b/composeApp/src/commonMain/kotlin/core/presentation/error_string_mapper/ErrorTextMapper.kt @@ -30,12 +30,15 @@ import grabit.composeapp.generated.resources.error__too_many_requests import grabit.composeapp.generated.resources.error__unauthorised import grabit.composeapp.generated.resources.error__unknown import grabit.composeapp.generated.resources.event_create_update_screen__capacity_error +import grabit.composeapp.generated.resources.event_create_update_screen__capacity_invalid_error import grabit.composeapp.generated.resources.event_create_update_screen__date_error import grabit.composeapp.generated.resources.event_create_update_screen__date_time_past import grabit.composeapp.generated.resources.event_create_update_screen__location_error import grabit.composeapp.generated.resources.event_create_update_screen__salary_amount_error +import grabit.composeapp.generated.resources.event_create_update_screen__salary_invalid_amount_error import grabit.composeapp.generated.resources.event_create_update_screen__time_error import grabit.composeapp.generated.resources.event_create_update_screen__title_error +import grabit.composeapp.generated.resources.register_screen__empty_name import org.jetbrains.compose.resources.ExperimentalResourceApi @OptIn(ExperimentalResourceApi::class) @@ -150,6 +153,14 @@ fun Error.asUiText(): UiErrorText { ) } } + + is ProfileError -> { + when (this) { + ProfileError.EMPTY_NAME -> UiErrorText.StringRes( + Res.string.register_screen__empty_name + ) + } + } } } @@ -186,6 +197,18 @@ fun Error.asUiText(): UiErrorText { ) } } + + is InvalidFieldError -> { + when (this) { + InvalidFieldError.CAPACITY -> UiErrorText.StringRes( + Res.string.event_create_update_screen__capacity_invalid_error + ) + + InvalidFieldError.SALARY_AMOUNT -> UiErrorText.StringRes( + Res.string.event_create_update_screen__salary_invalid_amount_error + ) + } + } } } diff --git a/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateEventValidation.kt b/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateEventValidation.kt index 21c88f2..c1bb08c 100644 --- a/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateEventValidation.kt +++ b/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateEventValidation.kt @@ -12,12 +12,16 @@ class CreateUpdateEventValidation { suspend fun validateInput( event: EventState, update: Boolean - ): Flow> = + ): Flow> = flow { if (event.title.isBlank()) { emit(ResultHandler.Error(CreateUpdateFormError.MissingFieldError.TITLE)) } else if (event.capacity.isBlank()) { emit(ResultHandler.Error(CreateUpdateFormError.MissingFieldError.CAPACITY)) + } else if (event.capacity.isNotBlank()) { + if (event.capacity.toIntOrNull() == null) { + emit(ResultHandler.Error(CreateUpdateFormError.InvalidFieldError.CAPACITY)) + } } else if (event.date == null) { emit(ResultHandler.Error(CreateUpdateFormError.MissingFieldError.DATE)) } else if (event.time == null) { @@ -32,6 +36,10 @@ class CreateUpdateEventValidation { emit(ResultHandler.Error(CreateUpdateFormError.MissingFieldError.LOCATION)) } else if (event.salaryAmount.isBlank()) { emit(ResultHandler.Error(CreateUpdateFormError.MissingFieldError.SALARY_AMOUNT)) + } else if (event.salaryAmount.isNotBlank()) { + if (event.salaryAmount.toFloatOrNull() == null) { + emit(ResultHandler.Error(CreateUpdateFormError.InvalidFieldError.SALARY_AMOUNT)) + } } else { emit(ResultHandler.Success(true)) } diff --git a/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateFormError.kt b/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateFormError.kt index 3a460fd..4fc72dd 100644 --- a/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateFormError.kt +++ b/composeApp/src/commonMain/kotlin/event/domain/CreateUpdateFormError.kt @@ -6,4 +6,8 @@ sealed interface CreateUpdateFormError : Error { enum class MissingFieldError : CreateUpdateFormError { TITLE, CAPACITY, DATE, TIME, DATE_TIME_PAST, LOCATION, SALARY_AMOUNT } + + enum class InvalidFieldError : CreateUpdateFormError { + CAPACITY, SALARY_AMOUNT + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/navigation/RootComponent.kt b/composeApp/src/commonMain/kotlin/navigation/RootComponent.kt index 327cbe8..9a64855 100644 --- a/composeApp/src/commonMain/kotlin/navigation/RootComponent.kt +++ b/composeApp/src/commonMain/kotlin/navigation/RootComponent.kt @@ -215,6 +215,7 @@ class RootComponent( RegisterStep3ScreenComponent( componentContext = context, registerUserUseCase = registerUserUseCase, + authValidation = authValidation, databaseClient = databaseClient, newUser = config.newUser, onNavigateToRegisterStepFinalScreen = {