feat: added profile edir screen

This commit is contained in:
dany
2025-11-21 23:35:02 +03:00
parent 15f8fe1d85
commit 336472a5b8
3 changed files with 154 additions and 7 deletions
@@ -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/"
}
@@ -93,7 +93,9 @@ fun TTasksNavHost(
composable(AppDestination.Profile.route)
{
ProfileScreen()
ProfileScreen(
snackbarHostState = snackbarHostState
)
}
}
}
@@ -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()
}
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))
}
}
}