You've already forked RekomenciMobile
feat: add experience fields
This commit is contained in:
@@ -28,7 +28,7 @@ data class ResumeCreationModel(
|
|||||||
data class WorkExperience(
|
data class WorkExperience(
|
||||||
val place: String,
|
val place: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val monthDuration: Int
|
val monthDuration: Int?
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Education(
|
data class Education(
|
||||||
@@ -60,9 +60,31 @@ enum class ExperienceType {
|
|||||||
MoreThan6
|
MoreThan6
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ResumeField {
|
sealed class ResumeField {
|
||||||
About,
|
data object About : ResumeField()
|
||||||
Position,
|
data object Position : ResumeField()
|
||||||
Experience,
|
data object Experience : ResumeField()
|
||||||
KeySkills
|
data object KeySkills : ResumeField()
|
||||||
|
|
||||||
|
data object City : ResumeField()
|
||||||
|
|
||||||
|
data class WorkExperiencePlace(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class WorkExperienceDescription(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class WorkExperienceMonthDuration(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
|
||||||
|
data class EducationPlace(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class EducationGrade(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class EducationSpecialization(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class EducationDescription(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class ProjectName(val id: Int) : ResumeField()
|
||||||
|
|
||||||
|
data class ProjectDescription(val id: Int) : ResumeField()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@ import com.prodhack.moscow2025.domain.models.AuthField
|
|||||||
import com.prodhack.moscow2025.domain.models.ExperienceType
|
import com.prodhack.moscow2025.domain.models.ExperienceType
|
||||||
import com.prodhack.moscow2025.domain.models.PhoneNumberPattern
|
import com.prodhack.moscow2025.domain.models.PhoneNumberPattern
|
||||||
import com.prodhack.moscow2025.domain.models.ResumeField
|
import com.prodhack.moscow2025.domain.models.ResumeField
|
||||||
import com.prodhack.moscow2025.presentation.screens.createResume.UIExperience
|
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
data class ValidationResult<T>(
|
data class ValidationResult<T>(
|
||||||
|
|||||||
+7
-3
@@ -62,7 +62,7 @@ fun TTTextField(
|
|||||||
val typography = MaterialTheme.typography
|
val typography = MaterialTheme.typography
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
FieldWrapper(modifier = modifier) {
|
FieldWrapper(modifier = modifier, disableHeightLimit = singleLine.not()) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = textFieldModifier
|
modifier = textFieldModifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -368,9 +368,13 @@ fun <T> TTTextFieldWithSearch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FieldWrapper(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
|
fun FieldWrapper(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
disableHeightLimit: Boolean = false,
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier.height(70.dp),
|
modifier.then(if (disableHeightLimit) Modifier else Modifier.height(70.dp)),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
+98
-3
@@ -11,6 +11,11 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonColors
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -20,6 +25,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.prodhack.moscow2025.R
|
import com.prodhack.moscow2025.R
|
||||||
@@ -30,6 +36,7 @@ import com.prodhack.moscow2025.presentation.components.standart.TTTextField
|
|||||||
import com.prodhack.moscow2025.presentation.components.standart.TTTextFieldWithDropdown
|
import com.prodhack.moscow2025.presentation.components.standart.TTTextFieldWithDropdown
|
||||||
import com.prodhack.moscow2025.presentation.components.standart.TTTextFieldWithSearch
|
import com.prodhack.moscow2025.presentation.components.standart.TTTextFieldWithSearch
|
||||||
import com.prodhack.moscow2025.presentation.theme.Paddings
|
import com.prodhack.moscow2025.presentation.theme.Paddings
|
||||||
|
import com.prodhack.moscow2025.presentation.theme.Shapes
|
||||||
import com.prodhack.moscow2025.presentation.utils.ui.noRippleClickable
|
import com.prodhack.moscow2025.presentation.utils.ui.noRippleClickable
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@@ -65,6 +72,12 @@ fun CreateResumeScreen(
|
|||||||
Text(text = "Новое резюме", style = typography.titleLarge, fontSize = 24.sp)
|
Text(text = "Новое резюме", style = typography.titleLarge, fontSize = 24.sp)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.size(24.dp))
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(Paddings.large))
|
Spacer(modifier = Modifier.height(Paddings.large))
|
||||||
TTTextField(
|
TTTextField(
|
||||||
value = formState.value.position,
|
value = formState.value.position,
|
||||||
@@ -72,7 +85,12 @@ fun CreateResumeScreen(
|
|||||||
label = "Какая должность вас интересует?",
|
label = "Какая должность вас интересует?",
|
||||||
error = formState.value.errors[ResumeField.Position]
|
error = formState.value.errors[ResumeField.Position]
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
TTTextField(
|
||||||
|
value = formState.value.city,
|
||||||
|
onValueChange = viewModel::onCityChange,
|
||||||
|
label = "Ваш город",
|
||||||
|
error = formState.value.errors[ResumeField.City]
|
||||||
|
)
|
||||||
TTTextField(
|
TTTextField(
|
||||||
value = formState.value.about,
|
value = formState.value.about,
|
||||||
onValueChange = viewModel::onAboutChange,
|
onValueChange = viewModel::onAboutChange,
|
||||||
@@ -81,7 +99,6 @@ fun CreateResumeScreen(
|
|||||||
label = "Расскажите о себе",
|
label = "Расскажите о себе",
|
||||||
error = formState.value.errors[ResumeField.Position]
|
error = formState.value.errors[ResumeField.Position]
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
|
||||||
TTTextFieldWithDropdown(
|
TTTextFieldWithDropdown(
|
||||||
value = formState.value.experience?.friendlyName ?: "",
|
value = formState.value.experience?.friendlyName ?: "",
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
@@ -95,7 +112,6 @@ fun CreateResumeScreen(
|
|||||||
},
|
},
|
||||||
onDropdownItemSelected = viewModel::onExperienceSelect
|
onDropdownItemSelected = viewModel::onExperienceSelect
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(Paddings.medium))
|
|
||||||
TTTextFieldWithSearch(
|
TTTextFieldWithSearch(
|
||||||
value = viewModel.skillSearchQuery.value,
|
value = viewModel.skillSearchQuery.value,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -151,8 +167,86 @@ fun CreateResumeScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(Paddings.large * 2))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
text = "Подробнее о вашем опыте работы:",
|
||||||
|
style = typography.titleMedium,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(Paddings.large))
|
Spacer(modifier = Modifier.height(Paddings.large))
|
||||||
|
|
||||||
|
|
||||||
|
formState.value.workExperience.forEachIndexed { index, workExp ->
|
||||||
|
Text(
|
||||||
|
text = "№${index + 1}:",
|
||||||
|
style = typography.labelLarge,
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||||
|
TTTextField(
|
||||||
|
value = workExp.place,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.changeWorkExperiencePlace(index, it)
|
||||||
|
},
|
||||||
|
label = "Место работы",
|
||||||
|
error = formState.value.errors[ResumeField.WorkExperiencePlace(index)]
|
||||||
|
)
|
||||||
|
|
||||||
|
TTTextField(
|
||||||
|
value = workExp.description,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.changeWorkExperiencePlace(index, it)
|
||||||
|
},
|
||||||
|
singleLine = false,
|
||||||
|
maxLines = 10,
|
||||||
|
label = "Расскажите подробнее",
|
||||||
|
error = formState.value.errors[ResumeField.WorkExperiencePlace(index)]
|
||||||
|
)
|
||||||
|
|
||||||
|
TTTextField(
|
||||||
|
value = workExp.place,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.changeWorkExperiencePlace(index, it)
|
||||||
|
},
|
||||||
|
label = "Место работы",
|
||||||
|
error = formState.value.errors[ResumeField.WorkExperiencePlace(index)]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formState.value.workExperience.isEmpty()){
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
text = "Пока ничего нет",
|
||||||
|
style = typography.labelLarge,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(Paddings.medium))
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
shape = Shapes.smallRoundedBox,
|
||||||
|
onClick = viewModel::addNewExperience,
|
||||||
|
colors = ButtonColors(
|
||||||
|
containerColor = colorScheme.onSecondary,
|
||||||
|
contentColor = colorScheme.secondary,
|
||||||
|
disabledContainerColor = colorScheme.onSecondary,
|
||||||
|
disabledContentColor = colorScheme.secondary
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Добавить",
|
||||||
|
style = typography.labelLarge,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(Paddings.large))
|
||||||
BigButton(
|
BigButton(
|
||||||
onClick = viewModel::submit,
|
onClick = viewModel::submit,
|
||||||
buttonText = "Узнать свою ЗП",
|
buttonText = "Узнать свою ЗП",
|
||||||
@@ -160,3 +254,4 @@ fun CreateResumeScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
+118
-15
@@ -3,10 +3,13 @@ package com.prodhack.moscow2025.presentation.screens.createResume
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.prodhack.moscow2025.domain.models.Education
|
||||||
|
import com.prodhack.moscow2025.domain.models.EducationGrades
|
||||||
import com.prodhack.moscow2025.domain.models.ExperienceType
|
import com.prodhack.moscow2025.domain.models.ExperienceType
|
||||||
import com.prodhack.moscow2025.domain.models.RegisterData
|
import com.prodhack.moscow2025.domain.models.Project
|
||||||
import com.prodhack.moscow2025.domain.models.ResumeCreationModel
|
import com.prodhack.moscow2025.domain.models.ResumeCreationModel
|
||||||
import com.prodhack.moscow2025.domain.models.ResumeField
|
import com.prodhack.moscow2025.domain.models.ResumeField
|
||||||
|
import com.prodhack.moscow2025.domain.models.WorkExperience
|
||||||
import com.prodhack.moscow2025.domain.usecase.auth.ValidateFieldsUseCase
|
import com.prodhack.moscow2025.domain.usecase.auth.ValidateFieldsUseCase
|
||||||
import com.prodhack.moscow2025.domain.usecase.resumes.CreateResumeUseCase
|
import com.prodhack.moscow2025.domain.usecase.resumes.CreateResumeUseCase
|
||||||
import com.prodhack.moscow2025.domain.usecase.resumes.SuggestSkillsUseCase
|
import com.prodhack.moscow2025.domain.usecase.resumes.SuggestSkillsUseCase
|
||||||
@@ -18,22 +21,27 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.android.annotation.KoinViewModel
|
import org.koin.android.annotation.KoinViewModel
|
||||||
|
import kotlin.collections.minus
|
||||||
import kotlin.math.exp
|
import kotlin.math.exp
|
||||||
|
|
||||||
data class ResumeFormState(
|
data class ResumeFormState(
|
||||||
val about: String = "",
|
val about: String = "",
|
||||||
val position: String = "",
|
val position: String = "",
|
||||||
val experience: UIExperience? = null,
|
val experience: UIExperienceCount? = null,
|
||||||
val keySkills: Set<String> = emptySet(),
|
val keySkills: Set<String> = emptySet(),
|
||||||
|
val city: String = "",
|
||||||
|
val workExperience: List<WorkExperience> = emptyList(),
|
||||||
|
val education: List<UIEducation> = emptyList(),
|
||||||
|
val projects: List<Project> = emptyList(),
|
||||||
val errors: Map<ResumeField, String> = emptyMap()
|
val errors: Map<ResumeField, String> = emptyMap()
|
||||||
)
|
)
|
||||||
|
|
||||||
sealed class UIExperience(val friendlyName: String) {
|
sealed class UIExperienceCount(val friendlyName: String) {
|
||||||
data object NoExperience : UIExperience("Без опыта")
|
data object NoExperience : UIExperienceCount("Без опыта")
|
||||||
data object LessThan1 : UIExperience("Меньше года")
|
data object LessThan1 : UIExperienceCount("Меньше года")
|
||||||
data object Between1And3 : UIExperience("От 1 до 3 лет")
|
data object Between1And3 : UIExperienceCount("От 1 до 3 лет")
|
||||||
data object Between3And6 : UIExperience("От 3 до 6 лет")
|
data object Between3And6 : UIExperienceCount("От 3 до 6 лет")
|
||||||
data object MoreThan6 : UIExperience("Более 6 лет")
|
data object MoreThan6 : UIExperienceCount("Более 6 лет")
|
||||||
|
|
||||||
fun mapToDomain(): ExperienceType =
|
fun mapToDomain(): ExperienceType =
|
||||||
when (this) {
|
when (this) {
|
||||||
@@ -45,6 +53,22 @@ sealed class UIExperience(val friendlyName: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class UIEducation(
|
||||||
|
val place: String,
|
||||||
|
val grade: UIEducationGrade,
|
||||||
|
val specialization: String,
|
||||||
|
val description: String
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class UIEducationGrade(val friendlyName: String) {
|
||||||
|
data object Common : UIEducationGrade("Общее")
|
||||||
|
data object Middle : UIEducationGrade("Среднее")
|
||||||
|
data object MiddleSpec : UIEducationGrade("Средне-специальное")
|
||||||
|
data object HighNotFinished : UIEducationGrade("Неоконченное высшее")
|
||||||
|
data object High : UIEducationGrade("Высшее")
|
||||||
|
data object Additional : UIEducationGrade("Другое")
|
||||||
|
}
|
||||||
|
|
||||||
@KoinViewModel
|
@KoinViewModel
|
||||||
class CreateResumeViewModel(
|
class CreateResumeViewModel(
|
||||||
private val suggestSkillsUseCase: SuggestSkillsUseCase,
|
private val suggestSkillsUseCase: SuggestSkillsUseCase,
|
||||||
@@ -57,6 +81,7 @@ class CreateResumeViewModel(
|
|||||||
private val _resumeFillState = MutableUIStateFlow<String>()
|
private val _resumeFillState = MutableUIStateFlow<String>()
|
||||||
val resumeFillState: StateFlow<UIState<String>> = _resumeFillState
|
val resumeFillState: StateFlow<UIState<String>> = _resumeFillState
|
||||||
|
|
||||||
|
// Simple fields
|
||||||
fun onAboutChange(value: String) {
|
fun onAboutChange(value: String) {
|
||||||
_formStateFillResume.update {
|
_formStateFillResume.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
@@ -75,7 +100,24 @@ class CreateResumeViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onExperienceSelect(value: UIExperience) {
|
fun onCityChange(value: String) {
|
||||||
|
_formStateFillResume.update {
|
||||||
|
it.copy(
|
||||||
|
city = value,
|
||||||
|
errors = it.errors - ResumeField.City
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val experienceOptions = listOf(
|
||||||
|
UIExperienceCount.NoExperience,
|
||||||
|
UIExperienceCount.LessThan1,
|
||||||
|
UIExperienceCount.Between1And3,
|
||||||
|
UIExperienceCount.Between3And6,
|
||||||
|
UIExperienceCount.MoreThan6
|
||||||
|
)
|
||||||
|
|
||||||
|
fun onExperienceSelect(value: UIExperienceCount) {
|
||||||
_formStateFillResume.update {
|
_formStateFillResume.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
experience = value,
|
experience = value,
|
||||||
@@ -84,6 +126,7 @@ class CreateResumeViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skills
|
||||||
fun onAddSkill(value: String) {
|
fun onAddSkill(value: String) {
|
||||||
_formStateFillResume.update {
|
_formStateFillResume.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
@@ -108,13 +151,73 @@ class CreateResumeViewModel(
|
|||||||
suggestSkillsUseCase(it).getOrNull() ?: emptyList()
|
suggestSkillsUseCase(it).getOrNull() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val experienceOptions = listOf(
|
// Experience work
|
||||||
UIExperience.NoExperience,
|
|
||||||
UIExperience.LessThan1,
|
fun addNewExperience() {
|
||||||
UIExperience.Between1And3,
|
_formStateFillResume.update {
|
||||||
UIExperience.Between3And6,
|
it.copy(
|
||||||
UIExperience.MoreThan6
|
workExperience = it.workExperience + WorkExperience("", "", null)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeExperience(id: Int) {
|
||||||
|
_formStateFillResume.update {
|
||||||
|
it.copy(
|
||||||
|
workExperience = it.workExperience.filterIndexed { index, _ -> index != id },
|
||||||
|
errors = it.errors
|
||||||
|
- ResumeField.WorkExperienceDescription(id)
|
||||||
|
- ResumeField.WorkExperienceMonthDuration(id)
|
||||||
|
- ResumeField.WorkExperiencePlace(id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeWorkExperiencePlace(index: Int, value: String) {
|
||||||
|
_formStateFillResume.update {
|
||||||
|
it.copy(
|
||||||
|
workExperience = it.workExperience.mapIndexed { ind, experience ->
|
||||||
|
if (ind == index) experience.copy(
|
||||||
|
place = value
|
||||||
|
) else experience
|
||||||
|
},
|
||||||
|
errors = it.errors
|
||||||
|
- ResumeField.WorkExperiencePlace(index)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeWorkExperienceMonthDuration(index: Int, value: String) {
|
||||||
|
_formStateFillResume.update {
|
||||||
|
it.copy(
|
||||||
|
workExperience = it.workExperience.mapIndexed { ind, experience ->
|
||||||
|
if (ind == index) {
|
||||||
|
value.toIntOrNull()?.let {
|
||||||
|
experience.copy(
|
||||||
|
monthDuration = it
|
||||||
|
)
|
||||||
|
} ?: experience
|
||||||
|
} else experience
|
||||||
|
},
|
||||||
|
errors = it.errors
|
||||||
|
- ResumeField.WorkExperienceDescription(index)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeWorkExperienceDescription(index: Int, value: String) {
|
||||||
|
_formStateFillResume.update {
|
||||||
|
it.copy(
|
||||||
|
workExperience = it.workExperience.mapIndexed { ind, experience ->
|
||||||
|
if (ind == index) experience.copy(
|
||||||
|
description = value
|
||||||
|
) else experience
|
||||||
|
},
|
||||||
|
errors = it.errors
|
||||||
|
- ResumeField.WorkExperienceDescription(index)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun submit() {
|
fun submit() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|||||||
Reference in New Issue
Block a user