diff --git a/app/src/main/java/com/prodhack/moscow2025/common/Constants.kt b/app/src/main/java/com/prodhack/moscow2025/common/Constants.kt index d66fabc..d05c5be 100644 --- a/app/src/main/java/com/prodhack/moscow2025/common/Constants.kt +++ b/app/src/main/java/com/prodhack/moscow2025/common/Constants.kt @@ -1,5 +1,5 @@ package com.prodhack.moscow2025.common object Constants { - const val BASE_API_URL = "https://hackaton.paas.itqdev.xyz/" + const val BASE_API_URL = "https://team-39-alpha-gm5qjkou.hack.prodcontest.ru/" } \ No newline at end of file diff --git a/app/src/main/java/com/prodhack/moscow2025/presentation/navigation/TTasksNavHost.kt b/app/src/main/java/com/prodhack/moscow2025/presentation/navigation/TTasksNavHost.kt index 988e0c6..9a85457 100644 --- a/app/src/main/java/com/prodhack/moscow2025/presentation/navigation/TTasksNavHost.kt +++ b/app/src/main/java/com/prodhack/moscow2025/presentation/navigation/TTasksNavHost.kt @@ -93,7 +93,9 @@ fun TTasksNavHost( composable(AppDestination.Profile.route) { - ProfileScreen() + ProfileScreen( + snackbarHostState = snackbarHostState + ) } } } diff --git a/app/src/main/java/com/prodhack/moscow2025/presentation/screens/profile/ProfileScreen.kt b/app/src/main/java/com/prodhack/moscow2025/presentation/screens/profile/ProfileScreen.kt index 0201697..2b3280c 100644 --- a/app/src/main/java/com/prodhack/moscow2025/presentation/screens/profile/ProfileScreen.kt +++ b/app/src/main/java/com/prodhack/moscow2025/presentation/screens/profile/ProfileScreen.kt @@ -1,14 +1,159 @@ package com.prodhack.moscow2025.presentation.screens.profile +import androidx.compose.foundation.Image +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.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import com.prodhack.moscow2025.presentation.utils.base.BaseViewModel +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.prodhack.moscow2025.R +import com.prodhack.moscow2025.domain.usecase.auth.AuthField +import com.prodhack.moscow2025.presentation.components.standart.BigButton +import com.prodhack.moscow2025.presentation.components.standart.TTTextField +import com.prodhack.moscow2025.presentation.theme.Paddings +import com.prodhack.moscow2025.presentation.utils.ErrorCollectorScope +import com.prodhack.moscow2025.presentation.utils.UIState import org.koin.androidx.compose.koinViewModel @Composable -fun ProfileScreen( - viewModel: ProfileScreenViewModel = koinViewModel() -) : BaseViewModel { +fun ErrorCollectorScope.ProfileScreen( + modifier: Modifier = Modifier, + snackbarHostState: SnackbarHostState, + viewModel: ProfileScreenViewModel = koinViewModel() +) { + val typography = androidx.compose.material3.MaterialTheme.typography + val formState by viewModel.formStateFillProfile.collectAsState() -} \ No newline at end of file + var errorText by remember { mutableStateOf("") } + val profileState by viewModel.profileState.collectAsStateWithCallbacks( + onInputError = { + errorText = it.error + }, + onConnectionError = { + errorText = "Нет подключения к сети" + }, + onUnexpectedError = { + errorText = it.error + }, + onLoading = { + errorText = "" + }, + onSuccess = { + errorText = "" + } + ) + + LaunchedEffect(profileState) { + if (profileState is UIState.Success) { + snackbarHostState.showSnackbar( + message = "Данные профиля обновлены", + duration = SnackbarDuration.Short + ) + } + } + + LaunchedEffect(errorText) { + if (errorText.isNotEmpty()) { + snackbarHostState.showSnackbar( + message = "Ошибка: $errorText", + duration = SnackbarDuration.Short + ) + } + } + + Box( + modifier = modifier + .fillMaxSize() + .imePadding() + .systemBarsPadding(), + contentAlignment = Alignment.BottomStart + ) { + Image( + painter = painterResource(R.drawable.lottie), + contentDescription = null, + modifier = Modifier + .align(Alignment.BottomStart) + .padding(start = 16.dp) + .fillMaxWidth(0.35f), + contentScale = ContentScale.FillWidth + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 30.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top + ) { + Spacer(Modifier.height(32.dp)) + Text( + text = "Профиль", + style = typography.titleLarge, + fontSize = 32.sp + ) + Spacer(Modifier.height(20.dp)) + TTTextField( + value = formState.firstName, + onValueChange = viewModel::onFirstNameChange, + label = "Имя", + error = formState.errors[AuthField.FirstName], + ) + Spacer(Modifier.height(12.dp)) + TTTextField( + value = formState.lastName, + onValueChange = viewModel::onLastNameChange, + label = "Фамилия", + error = formState.errors[AuthField.LastName], + ) + Spacer(Modifier.height(12.dp)) + TTTextField( + value = formState.email, + onValueChange = viewModel::onEmailChange, + label = "Email", + error = formState.errors[AuthField.Email], + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email) + ) + Spacer(Modifier.height(12.dp)) + TTTextField( + value = formState.phone, + onValueChange = viewModel::onPhoneChange, + label = "Телефон", + error = formState.errors[AuthField.Phone], + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone) + ) + + Spacer(modifier = Modifier.height(24.dp)) + BigButton( + onClick = viewModel::submit, + modifier = Modifier.fillMaxWidth(), + buttonText = "Сохранить", + isLoading = profileState is UIState.Loading + ) + Spacer(modifier = Modifier.height(48.dp)) + } + } +}